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