From f3bc0a1d840b4ce51657897c763bf4eca80bfd13 Mon Sep 17 00:00:00 2001 From: Marcel Otto Date: Sat, 23 Apr 2022 01:11:09 +0200 Subject: [PATCH] Use base of graph or default_base_iri as default in encoder --- CHANGELOG.md | 2 ++ lib/json/ld/encoder.ex | 16 ++++++++++++ test/unit/encoder_test.exs | 50 +++++++++++++++++++++++++++++++++++++- 3 files changed, 67 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e7850fe..7a1b288 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,8 @@ This project adheres to [Semantic Versioning](http://semver.org/) and - context maps can be given now with atom keys or as `RDF.PropertyMap` to `JSON.LD.context/2` and `JSON.LD.compact/3` +- the base IRI of a `RDF.Graph` or the `RDF.default_base_iri/0` is used as the + default `:base` in the `JSON.LD.Encoder` - `RDF.Vocabulary.Namespace` modules can be set as base IRI diff --git a/lib/json/ld/encoder.ex b/lib/json/ld/encoder.ex index 56e7ab7..6b4c41b 100644 --- a/lib/json/ld/encoder.ex +++ b/lib/json/ld/encoder.ex @@ -13,6 +13,8 @@ defmodule JSON.LD.Encoder do compaction is performed using this context - `:base`: : Allows to specify a base URI to be used during compaction (only when `:context` is provided). + Default is the base IRI of the encoded graph or if none present or in case of + encoded datasets the `RDF.default_base_iri/0`. - `:use_native_types`: If this flag is set to `true`, RDF literals with a datatype IRI that equals `xsd:integer` or `xsd:double` are converted to a JSON numbers and RDF literals with a datatype IRI that equals `xsd:boolean` are converted to `true` @@ -54,12 +56,26 @@ defmodule JSON.LD.Encoder do @impl RDF.Serialization.Encoder @spec encode(RDF.Data.t(), keyword) :: {:ok, String.t()} | {:error, any} def encode(data, opts \\ []) do + opts = set_base_iri(data, opts) + with {:ok, json_ld_object} <- from_rdf(data, opts), {:ok, json_ld_object} <- maybe_compact(json_ld_object, opts) do encode_json(json_ld_object, opts) end end + defp set_base_iri(%Graph{base_iri: base_iri}, opts) when not is_nil(base_iri) do + Keyword.put_new(opts, :base, IRI.to_string(base_iri)) + end + + defp set_base_iri(_, opts) do + if base = RDF.default_base_iri() do + Keyword.put_new(opts, :base, IRI.to_string(base)) + else + opts + end + end + # TODO: unless we find a way to allow more optimized encode! versions, remove this since it's never used (see the respective warning) @impl RDF.Serialization.Encoder @spec encode!(RDF.Data.t(), Options.convertible()) :: String.t() diff --git a/test/unit/encoder_test.exs b/test/unit/encoder_test.exs index 0987c94..fa7d8f4 100644 --- a/test/unit/encoder_test.exs +++ b/test/unit/encoder_test.exs @@ -3,7 +3,7 @@ defmodule JSON.LD.EncoderTest do doctest JSON.LD.Encoder - alias RDF.{Dataset, Graph, Description} + alias RDF.{Dataset, Graph, Description, IRI} alias RDF.NS import RDF.Sigils @@ -720,6 +720,54 @@ defmodule JSON.LD.EncoderTest do pretty: true ) == expected_result end + + test "base_iri of a RDF.Graph is used as the default for :base" do + context = %{ + "p" => %{ + "@id" => IRI.to_string(EX.p()), + "@type" => "@id" + } + } + + assert JSON.LD.Encoder.encode!( + Graph.new({EX.S, EX.p(), EX.O}, base_iri: EX), + context: context, + pretty: true + ) == + """ + { + "@context": { + "p": { + "@id": "#{EX.p()}", + "@type": "@id" + } + }, + "@id": "S", + "p": "O" + } + """ + |> String.trim() + + assert JSON.LD.Encoder.encode!( + Graph.new({EX.S, EX.p(), S.O}, base_iri: EX), + context: context, + base: S, + pretty: true + ) == + """ + { + "@context": { + "p": { + "@id": "#{EX.p()}", + "@type": "@id" + } + }, + "@id": "http://example.com/S", + "p": "O" + } + """ + |> String.trim() + end end describe "problems" do