Add :context option on JSON.LD.Encoder
This commit is contained in:
parent
d6cda29cea
commit
851a1b0c19
11
CHANGELOG.md
11
CHANGELOG.md
|
@ -5,6 +5,17 @@ This project adheres to [Semantic Versioning](http://semver.org/) and
|
|||
[Keep a CHANGELOG](http://keepachangelog.com).
|
||||
|
||||
|
||||
## Unreleased
|
||||
|
||||
### Added
|
||||
|
||||
- the `JSON.LD.Encoder` now supports implicit compaction by providing a context
|
||||
as a map or a URL string for a remote context with the new `:context` option
|
||||
|
||||
[Compare v0.3.4...HEAD](https://github.com/rdf-elixir/jsonld-ex/compare/v0.3.4...HEAD)
|
||||
|
||||
|
||||
|
||||
## 0.3.4 - 2021-12-13
|
||||
|
||||
Elixir versions < 1.10 are no longer supported
|
||||
|
|
|
@ -25,9 +25,11 @@ defmodule JSON.LD.Compaction do
|
|||
result
|
||||
end
|
||||
|
||||
if Context.empty?(active_context),
|
||||
do: result,
|
||||
else: Map.put(result, "@context", context["@context"] || context)
|
||||
cond do
|
||||
Context.empty?(active_context) -> result
|
||||
is_binary(context) -> Map.put(result, "@context", context)
|
||||
true -> Map.put(result, "@context", context["@context"] || context)
|
||||
end
|
||||
end
|
||||
|
||||
@spec do_compact(any, Context.t(), map, String.t() | nil, boolean) :: any
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
defmodule JSON.LD.Decoder do
|
||||
@moduledoc """
|
||||
A decoder for JSON-LD serializations to `RDF.Dataset`s.
|
||||
|
||||
As for all decoders of `RDF.Serialization.Format`s, you normally won't use these
|
||||
functions directly, but via one of the `read_` functions on the `JSON.LD` format
|
||||
module or the generic `RDF.Serialization` module.
|
||||
"""
|
||||
|
||||
use RDF.Serialization.Decoder
|
||||
|
|
|
@ -1,10 +1,34 @@
|
|||
defmodule JSON.LD.Encoder do
|
||||
@moduledoc """
|
||||
An encoder for JSON-LD serializations of RDF.ex data structures.
|
||||
|
||||
As for all encoders of `RDF.Serialization.Format`s, you normally won't use these
|
||||
functions directly, but via one of the `write_` functions on the `JSON.LD`
|
||||
format module or the generic `RDF.Serialization` module.
|
||||
|
||||
|
||||
## Options
|
||||
|
||||
- `:context`: When a context map or remote context URL string is given,
|
||||
compaction is performed using this context
|
||||
- `:base`: : Allows to specify a base URI to be used during compaction
|
||||
(only when `:context` is provided).
|
||||
- `: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`
|
||||
or `false` based on their lexical form. (default: `false`)
|
||||
- `:use_rdf_type`: Unless this flag is set to `true`, `rdf:type` predicates will be
|
||||
serialized as `@type` as long as the associated object is either an IRI or blank
|
||||
node identifier. (default: `false`)
|
||||
|
||||
The given options are also passed through to `Jason.encode/2`, so you can also
|
||||
provide any the options this function supports, most notably the `:pretty` option.
|
||||
|
||||
"""
|
||||
|
||||
use RDF.Serialization.Encoder
|
||||
|
||||
alias JSON.LD.Options
|
||||
alias JSON.LD.{Compaction, Options}
|
||||
|
||||
alias RDF.{
|
||||
BlankNode,
|
||||
|
@ -30,7 +54,8 @@ defmodule JSON.LD.Encoder do
|
|||
@impl RDF.Serialization.Encoder
|
||||
@spec encode(RDF.Data.t(), Options.t() | Enum.t()) :: {:ok, String.t()} | {:error, any}
|
||||
def encode(data, opts \\ []) do
|
||||
with {:ok, json_ld_object} <- from_rdf(data, opts) do
|
||||
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
|
||||
|
@ -40,9 +65,18 @@ defmodule JSON.LD.Encoder do
|
|||
@spec encode!(RDF.Data.t(), Options.t() | Enum.t()) :: String.t()
|
||||
@dialyzer {:nowarn_function, encode!: 1}
|
||||
def encode!(data, opts \\ []) do
|
||||
data
|
||||
|> from_rdf!(opts)
|
||||
|> encode_json!(opts)
|
||||
case encode(data, opts) do
|
||||
{:ok, result} -> result
|
||||
{:error, error} -> raise error
|
||||
end
|
||||
end
|
||||
|
||||
defp maybe_compact(json_ld_object, opts) do
|
||||
if context = Keyword.get(opts, :context) do
|
||||
{:ok, Compaction.compact(json_ld_object, context, opts)}
|
||||
else
|
||||
{:ok, json_ld_object}
|
||||
end
|
||||
end
|
||||
|
||||
@spec from_rdf(RDF.Data.t(), Options.t() | Enum.t()) :: {:ok, [map]} | {:error, any}
|
||||
|
@ -388,9 +422,4 @@ defmodule JSON.LD.Encoder do
|
|||
defp encode_json(value, opts) do
|
||||
Jason.encode(value, opts)
|
||||
end
|
||||
|
||||
@spec encode_json!(any, [Jason.encode_opt()]) :: String.t()
|
||||
defp encode_json!(value, opts) do
|
||||
Jason.encode!(value, opts)
|
||||
end
|
||||
end
|
||||
|
|
|
@ -572,6 +572,131 @@ defmodule JSON.LD.EncoderTest do
|
|||
end)
|
||||
end
|
||||
|
||||
describe "encode options" do
|
||||
test ":context with a context map" do
|
||||
graph =
|
||||
~I<http://manu.sporny.org/about#manu>
|
||||
|> S.givenName("Manu")
|
||||
|> S.familyName("Sporny")
|
||||
|> S.url(~I<http://manu.sporny.org/>)
|
||||
|> Graph.new()
|
||||
|
||||
context = %{
|
||||
"givenName" => "http://schema.org/givenName",
|
||||
"familyName" => "http://schema.org/familyName",
|
||||
"homepage" => %{
|
||||
"@id" => "http://schema.org/url",
|
||||
"@type" => "@id"
|
||||
}
|
||||
}
|
||||
|
||||
assert JSON.LD.Encoder.encode!(graph, context: context, pretty: true) ==
|
||||
"""
|
||||
{
|
||||
"@context": {
|
||||
"familyName": "http://schema.org/familyName",
|
||||
"givenName": "http://schema.org/givenName",
|
||||
"homepage": {
|
||||
"@id": "http://schema.org/url",
|
||||
"@type": "@id"
|
||||
}
|
||||
},
|
||||
"@id": "http://manu.sporny.org/about#manu",
|
||||
"familyName": "Sporny",
|
||||
"givenName": "Manu",
|
||||
"homepage": "http://manu.sporny.org/"
|
||||
}
|
||||
"""
|
||||
|> String.trim()
|
||||
end
|
||||
|
||||
test ":context with a remote context" do
|
||||
bypass = Bypass.open()
|
||||
|
||||
Bypass.expect(bypass, fn conn ->
|
||||
assert "GET" == conn.method
|
||||
assert "/test-context" == conn.request_path
|
||||
|
||||
context = %{
|
||||
"@context" => %{
|
||||
"givenName" => "http://schema.org/givenName",
|
||||
"familyName" => "http://schema.org/familyName",
|
||||
"homepage" => %{
|
||||
"@id" => "http://schema.org/url",
|
||||
"@type" => "@id"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Plug.Conn.resp(conn, 200, Jason.encode!(context))
|
||||
end)
|
||||
|
||||
remote_context = "http://localhost:#{bypass.port}/test-context"
|
||||
|
||||
graph =
|
||||
~I<http://manu.sporny.org/about#manu>
|
||||
|> S.givenName("Manu")
|
||||
|> S.familyName("Sporny")
|
||||
|> S.url(~I<http://manu.sporny.org/>)
|
||||
|> Graph.new()
|
||||
|
||||
assert JSON.LD.Encoder.encode!(graph, context: remote_context, pretty: true) ==
|
||||
"""
|
||||
{
|
||||
"@context": "#{remote_context}",
|
||||
"@id": "http://manu.sporny.org/about#manu",
|
||||
"familyName": "Sporny",
|
||||
"givenName": "Manu",
|
||||
"homepage": "http://manu.sporny.org/"
|
||||
}
|
||||
"""
|
||||
|> String.trim()
|
||||
end
|
||||
|
||||
test "compaction options" do
|
||||
graph =
|
||||
~I<http://manu.sporny.org/about#manu>
|
||||
|> S.givenName("Manu")
|
||||
|> S.familyName("Sporny")
|
||||
|> RDF.type(S.Person)
|
||||
|> EX.foo(3.14)
|
||||
|> EX.bar(EX.Bar)
|
||||
|> Graph.new()
|
||||
|
||||
context = %{
|
||||
"givenName" => "http://schema.org/givenName",
|
||||
"familyName" => "http://schema.org/familyName"
|
||||
}
|
||||
|
||||
assert JSON.LD.Encoder.encode!(graph,
|
||||
context: context,
|
||||
base: EX.__base_iri__(),
|
||||
use_native_types: true,
|
||||
use_rdf_type: true,
|
||||
pretty: true
|
||||
) ==
|
||||
"""
|
||||
{
|
||||
"@context": {
|
||||
"familyName": "http://schema.org/familyName",
|
||||
"givenName": "http://schema.org/givenName"
|
||||
},
|
||||
"@id": "http://manu.sporny.org/about#manu",
|
||||
"familyName": "Sporny",
|
||||
"givenName": "Manu",
|
||||
"http://example.com/bar": {
|
||||
"@id": "Bar"
|
||||
},
|
||||
"http://example.com/foo": 3.14,
|
||||
"http://www.w3.org/1999/02/22-rdf-syntax-ns#type": {
|
||||
"@id": "http://schema.org/Person"
|
||||
}
|
||||
}
|
||||
"""
|
||||
|> String.trim()
|
||||
end
|
||||
end
|
||||
|
||||
describe "problems" do
|
||||
%{
|
||||
"xsd:boolean as value" => {
|
||||
|
|
Loading…
Reference in New Issue