diff --git a/paket.dependencies b/paket.dependencies
index 76c60bd..5df60dd 100644
--- a/paket.dependencies
+++ b/paket.dependencies
@@ -21,5 +21,7 @@ nuget Costura.Fody
nuget Rdf.Vocabularies
nuget OpenCover
nuget Newtonsoft.Json ~> 9
+nuget JsonDiffPatch.Net
+nuget NodaTime.Serialization.JsonNet
gist tpluscode/a285267d2543466fc35c3a168c846f9f
\ No newline at end of file
diff --git a/paket.lock b/paket.lock
index bd05778..6a51a8d 100644
--- a/paket.lock
+++ b/paket.lock
@@ -17,11 +17,17 @@ NUGET
ImpromptuInterface (6.2.2)
InfoOf.Fody (1.0.4)
Fody (>= 1.29.2)
+ JsonDiffPatch.Net (1.0.5)
+ Newtonsoft.Json (>= 8.0.2)
json-ld.net (1.0.5)
Newtonsoft.Json (>= 6.0.4)
MethodTimer.Fody (1.16)
Fody (>= 1.29.2)
Newtonsoft.Json (9.0.1)
+ NodaTime (1.3.2)
+ NodaTime.Serialization.JsonNet (1.3.2)
+ Newtonsoft.Json (>= 4.5.11)
+ NodaTime (>= 1.3)
NullGuard.Fody (1.4.6)
Fody (>= 1.29.2)
NUnit (2.6.4)
@@ -32,4 +38,4 @@ NUGET
VDS.Common (1.6.4)
GIST
remote: tpluscode/a285267d2543466fc35c3a168c846f9f
- FULLPROJECT (eac8af5adfdcfc43b63a5d5edf88c082e83761e0)
\ No newline at end of file
+ FULLPROJECT (c9b7a831e53e929f2ecce09b14a61e28007b669f)
\ No newline at end of file
diff --git a/src/Documentation/CreatingContext/FluentContext/Readme.cs b/src/Documentation/CreatingContext/FluentContext/Readme.cs
index 3fba680..375799f 100644
--- a/src/Documentation/CreatingContext/FluentContext/Readme.cs
+++ b/src/Documentation/CreatingContext/FluentContext/Readme.cs
@@ -64,7 +64,7 @@ public void BuildComplexContextSimply()
// when
var context = new JObject(
Base.Is("http://example.com/"),
- Vocab.Is(new Uri("http://schema.org/")),
+ JsonLD.Entities.Context.Vocab.Is(new Uri("http://schema.org/")),
"dcterms".IsPrefixOf("http://purl.org/dc/terms/"),
"xsd".IsPrefixOf(new Uri("http://www.w3.org/2001/XMLSchema#")),
"title".IsProperty("dcterms:title"),
diff --git a/src/Documentation/CreatingContext/FluentContext/Readme.mkd b/src/Documentation/CreatingContext/FluentContext/Readme.mkd
index 85486a3..a4c166a 100644
--- a/src/Documentation/CreatingContext/FluentContext/Readme.mkd
+++ b/src/Documentation/CreatingContext/FluentContext/Readme.mkd
@@ -64,7 +64,7 @@ public void BuildComplexContextSimply()
// when
var context = new JObject(
Base.Is("http://example.com/"),
- Vocab.Is(new Uri("http://schema.org/")),
+ JsonLD.Entities.Context.Vocab.Is(new Uri("http://schema.org/")),
"dcterms".IsPrefixOf("http://purl.org/dc/terms/"),
"xsd".IsPrefixOf(new Uri("http://www.w3.org/2001/XMLSchema#")),
"title".IsProperty("dcterms:title"),
diff --git a/src/Documentation/Deserializing/LiteralValues/Readme.cs b/src/Documentation/Deserializing/LiteralValues/Readme.cs
index 12f73c1..137ff02 100644
--- a/src/Documentation/Deserializing/LiteralValues/Readme.cs
+++ b/src/Documentation/Deserializing/LiteralValues/Readme.cs
@@ -1,7 +1,7 @@
/**
# Documentation
-## Working with literal values
+## Deserializing literal values
As always, here are the required namespace imports.
**/
@@ -114,12 +114,17 @@ derived from the deafult `JsonConverter` it would fail to deserialize such liter
public class IPAddressConverter : JsonLdLiteralConverter
{
- public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+ protected override bool ShouldSerializeAsCompactLiteral(object value)
+ {
+ return true;
+ }
+
+ protected override void WriteJsonLdValue(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.WriteValue(value.ToString());
}
- protected override object DeserializeLiteral(JsonReader reader, Type objectType, JsonSerializer serializer)
+ protected override object ReadJsonLdLiteral(JsonReader reader, Type objectType, JsonSerializer serializer)
{
return IPAddress.Parse((string)reader.Value);
}
@@ -179,8 +184,9 @@ public void Can_deserialize_class_from_expanded_literal()
}
/**
-And lastly it is possible to serialize such an object to literal. Note that compacted value will always be produced, so it's important to
-create a fitting `@context` so that the JSON-LD document is valid and correct.
+And lastly it is possible to serialize such an object to literal. Note that the converter implementation
+always produces compacted value, so it's important to create a fitting `@context` so that the JSON-LD
+document is valid and correct.
**/
[Test]
diff --git a/src/Documentation/Deserializing/LiteralValues/Readme.mkd b/src/Documentation/Deserializing/LiteralValues/Readme.mkd
index 44b59e7..939da9f 100644
--- a/src/Documentation/Deserializing/LiteralValues/Readme.mkd
+++ b/src/Documentation/Deserializing/LiteralValues/Readme.mkd
@@ -1,6 +1,6 @@
# Documentation
-## Working with literal values
+## Deserializing literal values
As always, here are the required namespace imports.
@@ -113,12 +113,17 @@ derived from the deafult `JsonConverter` it would fail to deserialize such liter
``` c#
public class IPAddressConverter : JsonLdLiteralConverter
{
- public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
+ protected override bool ShouldSerializeAsCompactLiteral(object value)
+ {
+ return true;
+ }
+
+ protected override void WriteJsonLdValue(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.WriteValue(value.ToString());
}
- protected override object DeserializeLiteral(JsonReader reader, Type objectType, JsonSerializer serializer)
+ protected override object ReadJsonLdLiteral(JsonReader reader, Type objectType, JsonSerializer serializer)
{
return IPAddress.Parse((string)reader.Value);
}
@@ -178,8 +183,9 @@ public void Can_deserialize_class_from_expanded_literal()
}
```
-And lastly it is possible to serialize such an object to literal. Note that compacted value will always be produced, so it's important to
-create a fitting `@context` so that the JSON-LD document is valid and correct.
+And lastly it is possible to serialize such an object to literal. Note that the converter implementation
+always produces compacted value, so it's important to create a fitting `@context` so that the JSON-LD
+document is valid and correct.
``` c#
[Test]
diff --git a/src/Documentation/Documentation.csproj b/src/Documentation/Documentation.csproj
index 942ed25..e22c46b 100644
--- a/src/Documentation/Documentation.csproj
+++ b/src/Documentation/Documentation.csproj
@@ -23,6 +23,7 @@
prompt
4
true
+ ..\..\paket-files\tpluscode\a285267d2543466fc35c3a168c846f9f\UnitTests.ruleset
pdbonly
@@ -31,6 +32,8 @@
TRACE
prompt
4
+ true
+ ..\..\paket-files\tpluscode\a285267d2543466fc35c3a168c846f9f\UnitTests.ruleset
@@ -52,6 +55,7 @@
Code
+
@@ -108,6 +112,28 @@
+
+
+
+
+ ..\..\packages\NodaTime\lib\net35-Client\NodaTime.dll
+ True
+ True
+
+
+
+
+
+
+
+
+ ..\..\packages\NodaTime.Serialization.JsonNet\lib\net35-Client\NodaTime.Serialization.JsonNet.dll
+ True
+ True
+
+
+
+
@@ -119,5 +145,16 @@
+
+
+
+
+ ..\..\packages\Rdf.Vocabularies\lib\portable-net4+sl5+netcore45+wpa81+wp8+MonoAndroid1+MonoTouch1\Rdf.Vocabularies.dll
+ True
+ True
+
+
+
+
\ No newline at end of file
diff --git a/src/Documentation/Serializing/LiteralValues/Readme.cs b/src/Documentation/Serializing/LiteralValues/Readme.cs
new file mode 100644
index 0000000..33198b5
--- /dev/null
+++ b/src/Documentation/Serializing/LiteralValues/Readme.cs
@@ -0,0 +1,128 @@
+using JsonLD.Entities.Converters;
+using Newtonsoft.Json;
+using NodaTime.Serialization.JsonNet;
+using NUnit.Framework;
+
+/**
+# Documentation
+
+Related topic: [deserializing literals][deserialize-literals]
+
+## Serializing literal values
+
+In JSON-LD a literal value (ie. not a URI) are represented as JS objects, which
+contains the value as string and that value's type URI. For example a date
+would be represented as:
+
+``` json
+{
+ "@context": "http://example.com/vocab/",
+ "arrivalDate": {
+ "@value": "2017-01-14T14:50Z",
+ "@type": "http://www.w3.org/2001/XMLSchema#dateTime"
+ }
+}
+```
+
+### Serializing framework types
+
+JsonLd.Entities serializer will choose an appropriate [XSD data type][xsd] for
+matching .NET Framework primitive types and will output a JSON-LD object like the one
+shown above.
+
+**/
+
+public class SerializingFrameworkTypes
+{
+ private class TrainSchedule
+ {
+ public System.DateTime ArrivalDate => new System.DateTime(2017, 1, 14, 14, 50, 0);
+ }
+
+ [Test]
+ public void Serializes_builtin_types_as_expanded_literal()
+ {
+ // given
+ var serializer = new JsonLD.Entities.EntitySerializer();
+
+ // when
+ dynamic schedule = serializer.Serialize(new TrainSchedule());
+
+ // then
+ Assert.That((string)schedule.arrivalDate["@value"], Is.EqualTo("2017-01-14T14:50:00"));
+ Assert.That((string)schedule.arrivalDate["@type"], Is.EqualTo("http://www.w3.org/2001/XMLSchema#dateTime"));
+ }
+}
+
+/**
+
+The above works for all .NET numeric types, `DateTime`, `DateTimeOffset` and `TimeSpan`.
+
+The exceptions are `double` and `string` which all have their implicit typing in JSON and
+so they are serialized accoring to their default JavaScript rules while retaining the
+correct RDF typing (`xsd:double`, `xsd:boolean` and `xsd:string` accordingly). See the
+[JSON-LD spec](https://www.w3.org/TR/json-ld/#conversion-of-native-data-types).
+
+Note that integers are excempt from this rule, because as a generic term for all integral
+numbers, such datatype does not exist in .NET.
+
+### Serializing other types as literal
+
+It may be required to serialize instances of other classes as JSON-LD literals.
+Sticking to dates, one may prefer to use the `Instant` type from Jon Skeet's [NodaTime library][noda].
+
+To serialize any arbitrary type as an expanded literal one has to derive from
+`JsonLdLiteralConverter` and set it as the coverter for [property][prop-conv] or [class][class-conv].
+
+The converter class has one abstract and a number of virtual methods, which control
+the serialization output. In this example we use NodaTime's converter to write the `Instant` to
+JSON and set the `@type` to `xsd:dateTime`. Do have a look at this [deserialization page][deserialize-literals]
+for more examples.
+
+**/
+
+public class SerializingCustomTypesAsLiterals
+{
+ public class JsonLdNodaInstantConverter : JsonLdLiteralConverter
+ {
+ protected override void WriteJsonLdValue(JsonWriter writer, object value, JsonSerializer serializer)
+ {
+ NodaConverters.InstantConverter.WriteJson(writer, value, serializer);
+ }
+
+ protected override string GetJsonLdType(object value)
+ {
+ return Vocab.Xsd.dateTime;
+ }
+ }
+
+ public class NodaTimeTrainSchedule
+ {
+ [JsonConverter(typeof(JsonLdNodaInstantConverter))]
+ public NodaTime.Instant ArrivalDate => NodaTime.Instant.FromUtc(2017, 1, 14, 14, 50);
+ }
+
+ [Test]
+ public void Serializes_NodaTime_as_expanded_literal()
+ {
+ // given
+ var serializer = new JsonLD.Entities.EntitySerializer();
+
+ // when
+ dynamic schedule = serializer.Serialize(new NodaTimeTrainSchedule());
+
+ // then
+ Assert.That((string)schedule.arrivalDate["@value"], Is.EqualTo("2017-01-14T14:50:00Z"));
+ Assert.That((string)schedule.arrivalDate["@type"], Is.EqualTo("http://www.w3.org/2001/XMLSchema#dateTime"));
+ }
+}
+
+/**
+
+[deserialize-literals]: /wikibus/JsonLD.Entities/tree/master/src/Documentation/Deserializing/LiteralValues
+[xsd]: https://www.w3.org/TR/xmlschema-2/#built-in-datatypes
+[noda]: https://www.nuget.org/packages/NodaTime
+[class-conv]: http://www.newtonsoft.com/json/help/html/JsonConverterAttributeClass.htm
+[prop-conv]: http://www.newtonsoft.com/json/help/html/JsonConverterAttributeProperty.htm
+
+**/
\ No newline at end of file
diff --git a/src/Documentation/Serializing/LiteralValues/Readme.mkd b/src/Documentation/Serializing/LiteralValues/Readme.mkd
new file mode 100644
index 0000000..bd7b9bd
--- /dev/null
+++ b/src/Documentation/Serializing/LiteralValues/Readme.mkd
@@ -0,0 +1,124 @@
+``` c#
+using JsonLD.Entities.Converters;
+using Newtonsoft.Json;
+using NodaTime.Serialization.JsonNet;
+using NUnit.Framework;
+```
+
+# Documentation
+
+Related topic: [deserializing literals][deserialize-literals]
+
+## Serializing literal values
+
+In JSON-LD a literal value (ie. not a URI) are represented as JS objects, which
+contains the value as string and that value's type URI. For example a date
+would be represented as:
+
+``` json
+{
+ "@context": "http://example.com/vocab/",
+ "arrivalDate": {
+ "@value": "2017-01-14T14:50Z",
+ "@type": "http://www.w3.org/2001/XMLSchema#dateTime"
+ }
+}
+```
+
+### Serializing framework types
+
+JsonLd.Entities serializer will choose an appropriate [XSD data type][xsd] for
+matching .NET Framework primitive types and will output a JSON-LD object like the one
+shown above.
+
+``` c#
+public class SerializingFrameworkTypes
+{
+ private class TrainSchedule
+ {
+ public System.DateTime ArrivalDate => new System.DateTime(2017, 1, 14, 14, 50, 0);
+ }
+
+ [Test]
+ public void Serializes_builtin_types_as_expanded_literal()
+ {
+ // given
+ var serializer = new JsonLD.Entities.EntitySerializer();
+
+ // when
+ dynamic schedule = serializer.Serialize(new TrainSchedule());
+
+ // then
+ Assert.That((string)schedule.arrivalDate["@value"], Is.EqualTo("2017-01-14T14:50:00"));
+ Assert.That((string)schedule.arrivalDate["@type"], Is.EqualTo("http://www.w3.org/2001/XMLSchema#dateTime"));
+ }
+}
+```
+
+The above works for all .NET numeric types, `DateTime`, `DateTimeOffset` and `TimeSpan`.
+
+The exceptions are `double` and `string` which all have their implicit typing in JSON and
+so they are serialized accoring to their default JavaScript rules while retaining the
+correct RDF typing (`xsd:double`, `xsd:boolean` and `xsd:string` accordingly). See the
+[JSON-LD spec](https://www.w3.org/TR/json-ld/#conversion-of-native-data-types).
+
+Note that integers are excempt from this rule, because as a generic term for all integral
+numbers, such datatype does not exist in .NET.
+
+### Serializing other types as literal
+
+It may be required to serialize instances of other classes as JSON-LD literals.
+Sticking to dates, one may prefer to use the `Instant` type from Jon Skeet's [NodaTime library][noda].
+
+To serialize any arbitrary type as an expanded literal one has to derive from
+`JsonLdLiteralConverter` and set it as the coverter for [property][prop-conv] or [class][class-conv].
+
+The converter class has one abstract and a number of virtual methods, which control
+the serialization output. In this example we use NodaTime's converter to write the `Instant` to
+JSON and set the `@type` to `xsd:dateTime`. Do have a look at this [deserialization page][deserialize-literals]
+for more examples.
+
+``` c#
+public class SerializingCustomTypesAsLiterals
+{
+ public class JsonLdNodaInstantConverter : JsonLdLiteralConverter
+ {
+ protected override void WriteJsonLdValue(JsonWriter writer, object value, JsonSerializer serializer)
+ {
+ NodaConverters.InstantConverter.WriteJson(writer, value, serializer);
+ }
+
+ protected override string GetJsonLdType(object value)
+ {
+ return Vocab.Xsd.dateTime;
+ }
+ }
+
+ public class NodaTimeTrainSchedule
+ {
+ [JsonConverter(typeof(JsonLdNodaInstantConverter))]
+ public NodaTime.Instant ArrivalDate => NodaTime.Instant.FromUtc(2017, 1, 14, 14, 50);
+ }
+
+ [Test]
+ public void Serializes_NodaTime_as_expanded_literal()
+ {
+ // given
+ var serializer = new JsonLD.Entities.EntitySerializer();
+
+ // when
+ dynamic schedule = serializer.Serialize(new NodaTimeTrainSchedule());
+
+ // then
+ Assert.That((string)schedule.arrivalDate["@value"], Is.EqualTo("2017-01-14T14:50:00Z"));
+ Assert.That((string)schedule.arrivalDate["@type"], Is.EqualTo("http://www.w3.org/2001/XMLSchema#dateTime"));
+ }
+}
+```
+
+
+[deserialize-literals]: /wikibus/JsonLD.Entities/tree/master/src/Documentation/Deserializing/LiteralValues
+[xsd]: https://www.w3.org/TR/xmlschema-2/#built-in-datatypes
+[noda]: https://www.nuget.org/packages/NodaTime
+[class-conv]: http://www.newtonsoft.com/json/help/html/JsonConverterAttributeClass.htm
+[prop-conv]: http://www.newtonsoft.com/json/help/html/JsonConverterAttributeProperty.htm
diff --git a/src/Documentation/Serializing/WorkingWithURIs/Readme.cs b/src/Documentation/Serializing/WorkingWithURIs/Readme.cs
index cda8bfa..332fa56 100644
--- a/src/Documentation/Serializing/WorkingWithURIs/Readme.cs
+++ b/src/Documentation/Serializing/WorkingWithURIs/Readme.cs
@@ -52,7 +52,7 @@ would be interpreted as simple string and [upon removing the context](http://tin
}
```
-Let's see hot handle this in JsonLd.Entities:
+Let's see how to handle this in JsonLd.Entities:
**/
using System;
diff --git a/src/Documentation/Serializing/WorkingWithURIs/Readme.mkd b/src/Documentation/Serializing/WorkingWithURIs/Readme.mkd
index 66d5651..d47fe7b 100644
--- a/src/Documentation/Serializing/WorkingWithURIs/Readme.mkd
+++ b/src/Documentation/Serializing/WorkingWithURIs/Readme.mkd
@@ -51,7 +51,7 @@ would be interpreted as simple string and [upon removing the context](http://tin
}
```
-Let's see hot handle this in JsonLd.Entities:
+Let's see how to handle this in JsonLd.Entities:
``` c#
using System;
diff --git a/src/Documentation/paket.references b/src/Documentation/paket.references
index 7089c7f..aeff78a 100644
--- a/src/Documentation/paket.references
+++ b/src/Documentation/paket.references
@@ -1,4 +1,6 @@
Newtonsoft.Json
NUnit
json-ld.net
-GitVersionTask
\ No newline at end of file
+GitVersionTask
+NodaTime.Serialization.JsonNet
+Rdf.Vocabularies
\ No newline at end of file
diff --git a/src/JsonLD.Entities.Tests/Bindings/SerializingSteps.cs b/src/JsonLD.Entities.Tests/Bindings/SerializingSteps.cs
index 1cb979a..9c3ee77 100644
--- a/src/JsonLD.Entities.Tests/Bindings/SerializingSteps.cs
+++ b/src/JsonLD.Entities.Tests/Bindings/SerializingSteps.cs
@@ -1,7 +1,10 @@
using System;
+using System.Globalization;
using FakeItEasy;
using ImpromptuInterface;
+using JsonDiffPatchDotNet;
using JsonLD.Entities.Tests.Entities;
+using JsonLD.Entities.Tests.SpecflowHelpers;
using Newtonsoft.Json.Linq;
using NUnit.Framework;
using TechTalk.SpecFlow;
@@ -25,9 +28,7 @@ public void GivenAPersonWithoutId()
this.context.Object = new Person
{
Name = "Tomasz",
- Surname = "Pluskiewicz",
- BirthDate = new DateTime(1972, 9, 4),
- Age = 30
+ Surname = "Pluskiewicz"
};
}
@@ -38,6 +39,21 @@ public void GivenModelOfType(string typeName)
this.context.Object = Activator.CreateInstance(model);
}
+ [Given(@"model of type '(.*)'")]
+ public void GivenModelOfType(string typeName, Table table)
+ {
+ var modelType = Type.GetType(typeName, true);
+ this.context.Object = table.CreateInstance(modelType);
+ }
+
+ [Scope(Scenario = "Serializing DateTimeOffset value should produce typed literal")]
+ [Given(@"model has dateOff property equal to '(.*)'")]
+ public void GivenModelHasDateOff(string dateTimeOffset)
+ {
+ var allPrimitives = (AllPrimitives)this.context.Object;
+ allPrimitives.dateOff = DateTimeOffset.ParseExact(dateTimeOffset, "O", CultureInfo.InvariantCulture);
+ }
+
[Given(@"model has interest '(.*)'")]
public void GivenModelInterestsRDF(string value)
{
@@ -53,8 +69,10 @@ public void WhenTheObjectIsSerialized()
[Then(@"the resulting JSON-LD should be:")]
public void ThenTheResultingJsonLdShouldBe(string jObject)
{
+ // round-trip serialize/parse to remove typed JTokens
+ var jsonLdObject = JObject.Parse(this.context.JsonLdObject.ToString());
var expected = JObject.Parse(jObject);
- Assert.That(JToken.DeepEquals(this.context.JsonLdObject, expected), "Actual object was: {0}", this.context.JsonLdObject);
+ Assert.That(JToken.DeepEquals(jsonLdObject, expected), "Diff: {0}", new JsonDiffPatch().Diff(expected, jsonLdObject));
}
}
}
diff --git a/src/JsonLD.Entities.Tests/Entities/AllPrimitives.cs b/src/JsonLD.Entities.Tests/Entities/AllPrimitives.cs
new file mode 100644
index 0000000..153ecef
--- /dev/null
+++ b/src/JsonLD.Entities.Tests/Entities/AllPrimitives.cs
@@ -0,0 +1,41 @@
+// ReSharper disable InconsistentNaming
+#pragma warning disable SA1300 // Element must begin with upper-case letter
+using System;
+
+namespace JsonLD.Entities.Tests.Entities
+{
+ public class AllPrimitives
+ {
+ public string @string { get; set; }
+
+ public bool? @bool { get; set; }
+
+ public double? @double { get; set; }
+
+ public DateTime? date { get; set; }
+
+ public DateTimeOffset? dateOff { get; set; }
+
+ public decimal? @decimal { get; set; }
+
+ public long? @long { get; set; }
+
+ public ulong? @ulong { get; set; }
+
+ public int? @int { get; set; }
+
+ public uint? @uint { get; set; }
+
+ public short? @short { get; set; }
+
+ public ushort? @ushort { get; set; }
+
+ public byte? @byte { get; set; }
+
+ public sbyte? @sbyte { get; set; }
+
+ public float? @float { get; set; }
+
+ public TimeSpan? timeSpan { get; set; }
+ }
+}
\ No newline at end of file
diff --git a/src/JsonLD.Entities.Tests/Entities/Person.cs b/src/JsonLD.Entities.Tests/Entities/Person.cs
index 8630458..bb52d34 100644
--- a/src/JsonLD.Entities.Tests/Entities/Person.cs
+++ b/src/JsonLD.Entities.Tests/Entities/Person.cs
@@ -10,8 +10,6 @@ public class Person
public string Surname { get; set; }
- public int Age { get; set; }
-
- public DateTime BirthDate { get; set; }
+ public DateTime? BirthDate { get; set; }
}
}
diff --git a/src/JsonLD.Entities.Tests/JsonLD.Entities.Tests.csproj b/src/JsonLD.Entities.Tests/JsonLD.Entities.Tests.csproj
index 5ce8528..a975382 100644
--- a/src/JsonLD.Entities.Tests/JsonLD.Entities.Tests.csproj
+++ b/src/JsonLD.Entities.Tests/JsonLD.Entities.Tests.csproj
@@ -37,6 +37,8 @@
prompt
4
false
+ true
+ ..\..\paket-files\tpluscode\a285267d2543466fc35c3a168c846f9f\UnitTests.ruleset
@@ -68,6 +70,7 @@
True
DeserializingRDF.feature
+
@@ -92,6 +95,7 @@
True
Serializing.feature
+
@@ -203,6 +207,17 @@
+
+
+
+
+ ..\..\packages\JsonDiffPatch.Net\lib\net45\JsonDiffPatchDotNet.dll
+ True
+ True
+
+
+
+
diff --git a/src/JsonLD.Entities.Tests/Serializing.feature b/src/JsonLD.Entities.Tests/Serializing.feature
index a535584..6e3509a 100644
--- a/src/JsonLD.Entities.Tests/Serializing.feature
+++ b/src/JsonLD.Entities.Tests/Serializing.feature
@@ -8,9 +8,7 @@ Scenario: Serialize simple model with blank id
"""
{
"name": "Tomasz",
- "surname": "Pluskiewicz",
- "birthDate": "1972-09-04T00:00:00",
- "age": 30
+ "surname": "Pluskiewicz"
}
"""
@@ -70,4 +68,63 @@ Scenario: Serialize model with prefixed name in ClassAttribute
{
"@type": "ex:Person"
}
- """
\ No newline at end of file
+ """
+
+Scenario: Serializing primitive values should produce short literals for Boolean, Double and String
+ Given model of type 'JsonLD.Entities.Tests.Entities.AllPrimitives'
+ | Property | Value |
+ | string | Hello |
+ | double | 3.14 |
+ | bool | true |
+ When the object is serialized
+ Then the resulting JSON-LD should be:
+ """
+ {
+ "string": "Hello",
+ "double": 3.14,
+ "bool": true
+ }
+ """
+
+Scenario Outline: Serializing primitive values should produce typed literals
+ Given model of type 'JsonLD.Entities.Tests.Entities.AllPrimitives'
+ | Property | Value |
+ | | |
+ When the object is serialized
+ Then the resulting JSON-LD should be:
+ """
+ {
+ "": {
+ "@value": "",
+ "@type": "http://www.w3.org/2001/XMLSchema#"
+ }
+ }
+ """
+ Examples:
+ | Property | Value | JsonValue | XsdType |
+ | date | 2016-01-03 10:40 AM | 2016-01-03T10:40:00 | dateTime |
+ | decimal | 3.4 | 3.4 | decimal |
+ | long | 100 | 100 | long |
+ | ulong | 100 | 100 | unsignedLong |
+ | int | 1567 | 1567 | int |
+ | uint | 15 | 15 | unsignedInt |
+ | short | 17 | 17 | short |
+ | ushort | 3 | 3 | unsignedShort |
+ | byte | 20 | 20 | unsignedByte |
+ | sbyte | -3 | -3 | byte |
+ | float | 2.3456 | 2.3456 | float |
+ | timeSpan | 50.08:20:17 | P50DT8H20M17S | duration |
+
+Scenario: Serializing DateTimeOffset value should produce typed literal
+ Given model of type 'JsonLD.Entities.Tests.Entities.AllPrimitives'
+ And model has dateOff property equal to '2009-06-15T13:45:30.0000000-07:00'
+ When the object is serialized
+ Then the resulting JSON-LD should be:
+ """
+ {
+ "dateOff": {
+ "@value": "2009-06-15T13:45:30-07:00",
+ "@type": "http://www.w3.org/2001/XMLSchema#dateTime"
+ }
+ }
+ """
diff --git a/src/JsonLD.Entities.Tests/Serializing.feature.cs b/src/JsonLD.Entities.Tests/Serializing.feature.cs
index acc74d5..106f1cd 100644
--- a/src/JsonLD.Entities.Tests/Serializing.feature.cs
+++ b/src/JsonLD.Entities.Tests/Serializing.feature.cs
@@ -1,7 +1,7 @@
// ------------------------------------------------------------------------------
//
// This code was generated by SpecFlow (http://www.specflow.org/).
-// SpecFlow Version:2.0.0.0
+// SpecFlow Version:2.1.0.0
// SpecFlow Generator Version:2.0.0.0
//
// Changes to this file may cause incorrect behavior and will be lost if
@@ -15,7 +15,7 @@ namespace JsonLD.Entities.Tests
using TechTalk.SpecFlow;
- [System.CodeDom.Compiler.GeneratedCodeAttribute("TechTalk.SpecFlow", "2.0.0.0")]
+ [System.CodeDom.Compiler.GeneratedCodeAttribute("TechTalk.SpecFlow", "2.1.0.0")]
[System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[NUnit.Framework.TestFixtureAttribute()]
[NUnit.Framework.DescriptionAttribute("Serializing")]
@@ -76,8 +76,7 @@ public virtual void SerializeSimpleModelWithBlankId()
testRunner.When("the object is serialized", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When ");
#line hidden
#line 7
- testRunner.Then("the resulting JSON-LD should be:", "{\r\n \"name\": \"Tomasz\",\r\n \"surname\": \"Pluskiewicz\",\r\n \"birthDate\": \"1972-0" +
- "9-04T00:00:00\",\r\n \"age\": 30\r\n}", ((TechTalk.SpecFlow.Table)(null)), "Then ");
+ testRunner.Then("the resulting JSON-LD should be:", "{\r\n \"name\": \"Tomasz\",\r\n \"surname\": \"Pluskiewicz\"\r\n}", ((TechTalk.SpecFlow.Table)(null)), "Then ");
#line hidden
this.ScenarioCleanup();
}
@@ -92,16 +91,16 @@ public virtual void SerializeSimpleModelWithBlankId()
public virtual void SerializeModelWithSingleElementInSet(string type, string[] exampleTags)
{
TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Serialize model with single element in set", exampleTags);
-#line 17
+#line 15
this.ScenarioSetup(scenarioInfo);
-#line 18
+#line 16
testRunner.Given(string.Format("model of type \'{0}\'", type), ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given ");
-#line 19
+#line 17
testRunner.And("model has interest \'RDF\'", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And ");
-#line 20
+#line 18
testRunner.When("the object is serialized", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When ");
#line hidden
-#line 21
+#line 19
testRunner.Then("the resulting JSON-LD should be:", "{\r\n \"interests\": [ \"RDF\" ]\r\n}", ((TechTalk.SpecFlow.Table)(null)), "Then ");
#line hidden
this.ScenarioCleanup();
@@ -112,16 +111,16 @@ public virtual void SerializeModelWithSingleElementInSet(string type, string[] e
public virtual void SerializeModelWithSingleElementInList()
{
TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Serialize model with single element in list", ((string[])(null)));
-#line 35
+#line 33
this.ScenarioSetup(scenarioInfo);
-#line 36
+#line 34
testRunner.Given("model of type \'JsonLD.Entities.Tests.Entities.HasInterestsList\'", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given ");
-#line 37
+#line 35
testRunner.And("model has interest \'RDF\'", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And ");
-#line 38
+#line 36
testRunner.When("the object is serialized", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When ");
#line hidden
-#line 39
+#line 37
testRunner.Then("the resulting JSON-LD should be:", "{\r\n \"interests\": [ \"RDF\" ]\r\n}", ((TechTalk.SpecFlow.Table)(null)), "Then ");
#line hidden
this.ScenarioCleanup();
@@ -134,14 +133,14 @@ public virtual void SerializeModelWithSingleElementInList()
public virtual void SerializeModelWithEmptyCollection(string type, string[] exampleTags)
{
TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Serialize model with empty collection", exampleTags);
-#line 46
+#line 44
this.ScenarioSetup(scenarioInfo);
-#line 47
+#line 45
testRunner.Given(string.Format("model of type \'{0}\'", type), ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given ");
-#line 48
+#line 46
testRunner.When("the object is serialized", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When ");
#line hidden
-#line 49
+#line 47
testRunner.Then("the resulting JSON-LD should be:", "{\r\n}", ((TechTalk.SpecFlow.Table)(null)), "Then ");
#line hidden
this.ScenarioCleanup();
@@ -152,18 +151,110 @@ public virtual void SerializeModelWithEmptyCollection(string type, string[] exam
public virtual void SerializeModelWithPrefixedNameInClassAttribute()
{
TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Serialize model with prefixed name in ClassAttribute", ((string[])(null)));
-#line 59
+#line 57
this.ScenarioSetup(scenarioInfo);
-#line 60
+#line 58
testRunner.Given("model of type \'JsonLD.Entities.Tests.Entities.PersonWithPrefixedClass\'", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given ");
#line hidden
-#line 61
+#line 59
testRunner.And("@context is:", "{\r\n \"ex\": \"http://example.com/ontology#\"\r\n}", ((TechTalk.SpecFlow.Table)(null)), "And ");
-#line 67
+#line 65
testRunner.When("the object is serialized", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When ");
#line hidden
-#line 68
+#line 66
testRunner.Then("the resulting JSON-LD should be:", "{\r\n \"@type\": \"ex:Person\"\r\n}", ((TechTalk.SpecFlow.Table)(null)), "Then ");
+#line hidden
+ this.ScenarioCleanup();
+ }
+
+ [NUnit.Framework.TestAttribute()]
+ [NUnit.Framework.DescriptionAttribute("Serializing primitive values should produce short literals for Boolean, Double an" +
+ "d String")]
+ public virtual void SerializingPrimitiveValuesShouldProduceShortLiteralsForBooleanDoubleAndString()
+ {
+ TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Serializing primitive values should produce short literals for Boolean, Double an" +
+ "d String", ((string[])(null)));
+#line 73
+this.ScenarioSetup(scenarioInfo);
+#line hidden
+ TechTalk.SpecFlow.Table table1 = new TechTalk.SpecFlow.Table(new string[] {
+ "Property",
+ "Value"});
+ table1.AddRow(new string[] {
+ "string",
+ "Hello"});
+ table1.AddRow(new string[] {
+ "double",
+ "3.14"});
+ table1.AddRow(new string[] {
+ "bool",
+ "true"});
+#line 74
+ testRunner.Given("model of type \'JsonLD.Entities.Tests.Entities.AllPrimitives\'", ((string)(null)), table1, "Given ");
+#line 79
+ testRunner.When("the object is serialized", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When ");
+#line hidden
+#line 80
+ testRunner.Then("the resulting JSON-LD should be:", "{\r\n\"string\": \"Hello\",\r\n\"double\": 3.14,\r\n\"bool\": true\r\n}", ((TechTalk.SpecFlow.Table)(null)), "Then ");
+#line hidden
+ this.ScenarioCleanup();
+ }
+
+ [NUnit.Framework.TestAttribute()]
+ [NUnit.Framework.DescriptionAttribute("Serializing primitive values should produce typed literals")]
+ [NUnit.Framework.TestCaseAttribute("date", "2016-01-03 10:40 AM", "2016-01-03T10:40:00", "dateTime", new string[0])]
+ [NUnit.Framework.TestCaseAttribute("decimal", "3.4", "3.4", "decimal", new string[0])]
+ [NUnit.Framework.TestCaseAttribute("long", "100", "100", "long", new string[0])]
+ [NUnit.Framework.TestCaseAttribute("ulong", "100", "100", "unsignedLong", new string[0])]
+ [NUnit.Framework.TestCaseAttribute("int", "1567", "1567", "int", new string[0])]
+ [NUnit.Framework.TestCaseAttribute("uint", "15", "15", "unsignedInt", new string[0])]
+ [NUnit.Framework.TestCaseAttribute("short", "17", "17", "short", new string[0])]
+ [NUnit.Framework.TestCaseAttribute("ushort", "3", "3", "unsignedShort", new string[0])]
+ [NUnit.Framework.TestCaseAttribute("byte", "20", "20", "unsignedByte", new string[0])]
+ [NUnit.Framework.TestCaseAttribute("sbyte", "-3", "-3", "byte", new string[0])]
+ [NUnit.Framework.TestCaseAttribute("float", "2.3456", "2.3456", "float", new string[0])]
+ [NUnit.Framework.TestCaseAttribute("timeSpan", "50.08:20:17", "P50DT8H20M17S", "duration", new string[0])]
+ public virtual void SerializingPrimitiveValuesShouldProduceTypedLiterals(string property, string value, string jsonValue, string xsdType, string[] exampleTags)
+ {
+ TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Serializing primitive values should produce typed literals", exampleTags);
+#line 89
+this.ScenarioSetup(scenarioInfo);
+#line hidden
+ TechTalk.SpecFlow.Table table2 = new TechTalk.SpecFlow.Table(new string[] {
+ "Property",
+ "Value"});
+ table2.AddRow(new string[] {
+ string.Format("{0}", property),
+ string.Format("{0}", value)});
+#line 90
+ testRunner.Given("model of type \'JsonLD.Entities.Tests.Entities.AllPrimitives\'", ((string)(null)), table2, "Given ");
+#line 93
+ testRunner.When("the object is serialized", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When ");
+#line hidden
+#line 94
+ testRunner.Then("the resulting JSON-LD should be:", string.Format("{{\r\n\"{0}\": {{\r\n\"@value\": \"{1}\",\r\n\"@type\": \"http://www.w3.org/2001/XMLSchema#{2}\"\r" +
+ "\n}}\r\n}}", property, jsonValue, xsdType), ((TechTalk.SpecFlow.Table)(null)), "Then ");
+#line hidden
+ this.ScenarioCleanup();
+ }
+
+ [NUnit.Framework.TestAttribute()]
+ [NUnit.Framework.DescriptionAttribute("Serializing DateTimeOffset value should produce typed literal")]
+ public virtual void SerializingDateTimeOffsetValueShouldProduceTypedLiteral()
+ {
+ TechTalk.SpecFlow.ScenarioInfo scenarioInfo = new TechTalk.SpecFlow.ScenarioInfo("Serializing DateTimeOffset value should produce typed literal", ((string[])(null)));
+#line 118
+this.ScenarioSetup(scenarioInfo);
+#line 119
+ testRunner.Given("model of type \'JsonLD.Entities.Tests.Entities.AllPrimitives\'", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "Given ");
+#line 120
+ testRunner.And("model has dateOff property equal to \'2009-06-15T13:45:30.0000000-07:00\'", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "And ");
+#line 121
+ testRunner.When("the object is serialized", ((string)(null)), ((TechTalk.SpecFlow.Table)(null)), "When ");
+#line hidden
+#line 122
+ testRunner.Then("the resulting JSON-LD should be:", "{\r\n\"dateOff\": {\r\n\"@value\": \"2009-06-15T13:45:30-07:00\",\r\n\"@type\": \"http://www.w3." +
+ "org/2001/XMLSchema#dateTime\"\r\n}\r\n}", ((TechTalk.SpecFlow.Table)(null)), "Then ");
#line hidden
this.ScenarioCleanup();
}
diff --git a/src/JsonLD.Entities.Tests/SpecflowHelpers/TableExtensions.cs b/src/JsonLD.Entities.Tests/SpecflowHelpers/TableExtensions.cs
new file mode 100644
index 0000000..744f793
--- /dev/null
+++ b/src/JsonLD.Entities.Tests/SpecflowHelpers/TableExtensions.cs
@@ -0,0 +1,24 @@
+using System;
+using System.Reflection;
+using TechTalk.SpecFlow;
+using TechTalk.SpecFlow.Assist;
+
+namespace JsonLD.Entities.Tests.SpecflowHelpers
+{
+ public static class TableExtensions
+ {
+ private static readonly MethodInfo RealCreateInstance;
+
+ static TableExtensions()
+ {
+ RealCreateInstance = typeof(TableHelperExtensionMethods).GetMethod("CreateInstance", new[] { typeof(Table) });
+ }
+
+ public static object CreateInstance(this Table table, Type objecType)
+ {
+ var createInstance = RealCreateInstance.MakeGenericMethod(objecType);
+
+ return createInstance.Invoke(null, new object[] { table });
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/JsonLD.Entities.Tests/paket.references b/src/JsonLD.Entities.Tests/paket.references
index ebcf370..d6c55b9 100644
--- a/src/JsonLD.Entities.Tests/paket.references
+++ b/src/JsonLD.Entities.Tests/paket.references
@@ -6,4 +6,5 @@ ImpromptuInterface
FakeItEasy
json-ld.net
StyleCop.Analyzers
-Rdf.Vocabularies
\ No newline at end of file
+Rdf.Vocabularies
+JsonDiffPatch.Net
\ No newline at end of file
diff --git a/src/JsonLD.Entities/Converters/BuiltInTypesLiteralConverter.cs b/src/JsonLD.Entities/Converters/BuiltInTypesLiteralConverter.cs
new file mode 100644
index 0000000..d9e4be5
--- /dev/null
+++ b/src/JsonLD.Entities/Converters/BuiltInTypesLiteralConverter.cs
@@ -0,0 +1,50 @@
+using System;
+using System.Xml;
+using Newtonsoft.Json;
+using NullGuard;
+
+namespace JsonLD.Entities.Converters
+{
+ ///
+ /// Converts .NET framework data types as expanded literals typed with XSD data types accordingly
+ ///
+ public class BuiltInTypesLiteralConverter : JsonLdLiteralConverter
+ {
+ ///
+ /// Implicitly typed JS values are serialized as compact literals.
+ ///
+ protected override bool ShouldSerializeAsCompactLiteral(object value)
+ {
+ return value?.GetType().HasImplicitlyTypedJsonType() == true;
+ }
+
+ ///
+ /// Writes the RDF string representation of XSD types to JSON.
+ ///
+ protected override void WriteJsonLdValue(JsonWriter writer, object value, JsonSerializer serializer)
+ {
+ if (value?.GetType().HasImplicitlyTypedJsonType() == true)
+ {
+ writer.WriteValue(value);
+ }
+ else if (value is TimeSpan)
+ {
+ writer.WriteValue(XmlConvert.ToString((TimeSpan)value));
+ }
+ else
+ {
+ var valueString = JsonConvert.ToString(value);
+ writer.WriteValue(valueString.Trim('"')); // for the weirdest of reasons, DateTime is double-quoted
+ }
+ }
+
+ ///
+ /// Gets the XSD data type URI matching the value.
+ ///
+ protected override string GetJsonLdType([AllowNull] object value)
+ {
+ var type = value?.GetType();
+ return type.GetXsdType();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/JsonLD.Entities/Converters/JsonLdLiteralConverter.cs b/src/JsonLD.Entities/Converters/JsonLdLiteralConverter.cs
index b7b5fe2..7ee3184 100644
--- a/src/JsonLD.Entities/Converters/JsonLdLiteralConverter.cs
+++ b/src/JsonLD.Entities/Converters/JsonLdLiteralConverter.cs
@@ -8,7 +8,7 @@ namespace JsonLD.Entities.Converters
///
/// pending doc
///
- public class JsonLdLiteralConverter : JsonConverter
+ public abstract class JsonLdLiteralConverter : JsonConverter
{
private static readonly JsonLdSerializer LiteralSerializer;
@@ -28,7 +28,19 @@ static JsonLdLiteralConverter()
///
public override void WriteJson(JsonWriter writer, [AllowNull] object value, JsonSerializer serializer)
{
- writer.WriteValue(value);
+ if (this.ShouldSerializeAsCompactLiteral(value))
+ {
+ this.WriteJsonLdValue(writer, value, serializer);
+ return;
+ }
+
+ writer.WriteStartObject();
+ writer.WritePropertyName(JsonLdKeywords.Value);
+
+ this.WriteJsonLdValue(writer, value, serializer);
+
+ writer.WritePropertyName(JsonLdKeywords.Type);
+ writer.WriteValue(this.GetJsonLdType(value));
}
///
@@ -42,7 +54,7 @@ public sealed override object ReadJson(
{
if (reader.TokenType != JsonToken.StartObject)
{
- return this.DeserializeLiteral(reader, objectType, serializer);
+ return this.ReadJsonLdLiteral(reader, objectType, serializer);
}
object value = null;
@@ -50,10 +62,10 @@ public sealed override object ReadJson(
{
reader.Read();
- if (reader.TokenType == JsonToken.PropertyName && Equals(reader.Value, "@value"))
+ if (reader.TokenType == JsonToken.PropertyName && Equals(reader.Value, JsonLdKeywords.Value))
{
reader.Read();
- value = this.DeserializeLiteral(reader, objectType, serializer);
+ value = this.ReadJsonLdLiteral(reader, objectType, serializer);
}
else
{
@@ -72,12 +84,39 @@ public override bool CanConvert(Type objectType)
return true;
}
+ ///
+ /// When overriden in derived classes, it returns a value to determine
+ /// whether a compacted or expanded JSON-LD should be produced
+ ///
+ protected virtual bool ShouldSerializeAsCompactLiteral(object value)
+ {
+ return false;
+ }
+
+ ///
+ /// When implemented in derived class, returns an RDF data type name for the value
+ ///
+ protected virtual string GetJsonLdType(object value)
+ {
+ throw new NotImplementedException("To serialize as expanded literals it is necessary to override the JsonLdLiteralConverter#GetJsonLdType method");
+ }
+
///
/// When implemented in derived classes can be used to customize deserialization logic for literal value
///
- protected virtual object DeserializeLiteral(JsonReader reader, Type objectType, JsonSerializer serializer)
+ protected virtual object ReadJsonLdLiteral(JsonReader reader, Type objectType, JsonSerializer serializer)
{
return LiteralSerializer.Deserialize(reader, objectType);
}
+
+ ///
+ /// When implemented in derived class writes the RDF string representation
+ /// of
+ ///
+ ///
+ /// should only use the
+ /// method for writing the RDF value
+ ///
+ protected abstract void WriteJsonLdValue(JsonWriter writer, object value, JsonSerializer serializer);
}
}
diff --git a/src/JsonLD.Entities/JsonLD.Entities.csproj b/src/JsonLD.Entities/JsonLD.Entities.csproj
index 1c80555..8ce7c3e 100644
--- a/src/JsonLD.Entities/JsonLD.Entities.csproj
+++ b/src/JsonLD.Entities/JsonLD.Entities.csproj
@@ -35,6 +35,8 @@
prompt
4
bin\Release\JsonLD.Entities.XML
+ true
+ ..\..\paket-files\tpluscode\a285267d2543466fc35c3a168c846f9f\Library.ruleset
@@ -59,6 +61,7 @@
+
@@ -177,6 +180,17 @@
+
+
+
+
+ ..\..\packages\Rdf.Vocabularies\lib\portable-net4+sl5+netcore45+wpa81+wp8+MonoAndroid1+MonoTouch1\Rdf.Vocabularies.dll
+ True
+ True
+
+
+
+
diff --git a/src/JsonLD.Entities/JsonLdContractResolver.cs b/src/JsonLD.Entities/JsonLdContractResolver.cs
index 94e0272..e9d569a 100644
--- a/src/JsonLD.Entities/JsonLdContractResolver.cs
+++ b/src/JsonLD.Entities/JsonLdContractResolver.cs
@@ -65,7 +65,7 @@ public override JsonContract ResolveContract(Type type)
}
else if (contract is JsonPrimitiveContract && contract.Converter == null)
{
- contract.Converter = new JsonLdLiteralConverter();
+ contract.Converter = new BuiltInTypesLiteralConverter();
}
return contract;
diff --git a/src/JsonLD.Entities/JsonLdKeywords.cs b/src/JsonLD.Entities/JsonLdKeywords.cs
index bc5a586..6bc7aa6 100644
--- a/src/JsonLD.Entities/JsonLdKeywords.cs
+++ b/src/JsonLD.Entities/JsonLdKeywords.cs
@@ -59,6 +59,11 @@ public static class JsonLdKeywords
///
public const string Index = "@index";
+ ///
+ /// @value keyword
+ ///
+ public const string Value = "@value";
+
private static readonly IDictionary KnownPropertyNames = new Dictionary();
static JsonLdKeywords()
diff --git a/src/JsonLD.Entities/TypeExtension.cs b/src/JsonLD.Entities/TypeExtension.cs
index 7e56eab..ffef035 100644
--- a/src/JsonLD.Entities/TypeExtension.cs
+++ b/src/JsonLD.Entities/TypeExtension.cs
@@ -6,6 +6,8 @@
using ImpromptuInterface;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
+using NullGuard;
+using Vocab;
namespace JsonLD.Entities
{
@@ -14,6 +16,28 @@ namespace JsonLD.Entities
///
public static class TypeExtension
{
+ private static readonly IDictionary XsdDatatypeMappings;
+
+ static TypeExtension()
+ {
+ XsdDatatypeMappings = new Dictionary
+ {
+ [typeof(int)] = Xsd.@int,
+ [typeof(uint)] = Xsd.unsignedInt,
+ [typeof(long)] = Xsd.@long,
+ [typeof(ulong)] = Xsd.unsignedLong,
+ [typeof(short)] = Xsd.@short,
+ [typeof(ushort)] = Xsd.unsignedShort,
+ [typeof(sbyte)] = Xsd.@byte,
+ [typeof(byte)] = Xsd.unsignedByte,
+ [typeof(DateTime)] = Xsd.dateTime,
+ [typeof(DateTimeOffset)] = Xsd.dateTime,
+ [typeof(TimeSpan)] = Xsd.duration,
+ [typeof(float)] = Xsd.@float,
+ [typeof(decimal)] = Xsd.@decimal,
+ };
+ }
+
///
/// Gets the class identifier for an entity type.
///
@@ -57,6 +81,31 @@ internal static bool IsMarkedForCompaction(this Type type)
return type.GetCustomAttributes(typeof(SerializeCompactedAttribute), true).Any();
}
+ ///
+ /// Determines whether the type has implicit type in JSON (ie. doesn't require explicit JSON-LD typing)
+ ///
+ internal static bool HasImplicitlyTypedJsonType([AllowNull] this Type type)
+ {
+ return type == null
+ || type == typeof(bool)
+ || type == typeof(double)
+ || type == typeof(string);
+ }
+
+ ///
+ /// Gets the URI of an XSD datatype for
+ ///
+ internal static string GetXsdType(this Type type)
+ {
+ string xsdTypeName;
+ if (XsdDatatypeMappings.TryGetValue(type, out xsdTypeName) == false)
+ {
+ throw new ArgumentOutOfRangeException(nameof(type), $"Type {type.Name} doesn't have an XSD equivalent");
+ }
+
+ return xsdTypeName;
+ }
+
private static PropertyInfo GetAnnotatedTypeProperty(this Type type)
{
return (from prop in type.GetProperties(BindingFlags.Static | BindingFlags.NonPublic | BindingFlags.Public)
diff --git a/src/JsonLD.Entities/paket.references b/src/JsonLD.Entities/paket.references
index 51a7af9..9b88160 100644
--- a/src/JsonLD.Entities/paket.references
+++ b/src/JsonLD.Entities/paket.references
@@ -4,4 +4,5 @@ NullGuard.Fody
InfoOf.Fody
ImpromptuInterface
Costura.Fody
-StyleCop.Analyzers
\ No newline at end of file
+StyleCop.Analyzers
+Rdf.Vocabularies
\ No newline at end of file