Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions NuGet.config

This file was deleted.

1 change: 0 additions & 1 deletion Schema.NET.sln
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
build.cake = build.cake
Key.snk = Key.snk
MinimumRecommendedRulesWithStyleCop.ruleset = MinimumRecommendedRulesWithStyleCop.ruleset
NuGet.config = NuGet.config
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Schema.NET.Tool", "Source\Schema.NET.Tool\Schema.NET.Tool.csproj", "{3CED3D1A-AB36-4B39-86DC-910BF8237DE9}"
Expand Down
59 changes: 59 additions & 0 deletions Source/Schema.NET/ContextJsonConverter.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
namespace Schema.NET
{
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

/// <summary>
/// Converts a <see cref="JsonLdContext"/> object to and from JSON.
/// </summary>
/// <seealso cref="Newtonsoft.Json.JsonConverter" />
public class ContextJsonConverter : JsonConverter<JsonLdContext>
{
/// <inheritdoc />
public override JsonLdContext ReadJson(JsonReader reader, Type objectType, JsonLdContext existingValue, bool hasExistingValue, JsonSerializer serializer)
{
var context = hasExistingValue ? existingValue : new JsonLdContext();

string name;
string language;
if (reader.TokenType == JsonToken.String)
{
name = (string)reader.Value;
language = null;
}
else
{
var o = JObject.Load(reader);

var nameProperty = o.Property("name", StringComparison.OrdinalIgnoreCase);
name = nameProperty?.Value?.ToString() ?? "http://schema.org";

var languageProperty = o.Property("@language", StringComparison.OrdinalIgnoreCase);
language = languageProperty?.Value?.ToString();
}

context.Name = name;
context.Language = language;
return context;
}

/// <inheritdoc />
public override void WriteJson(JsonWriter writer, JsonLdContext value, JsonSerializer serializer)
{
if (string.IsNullOrWhiteSpace(value.Language))
{
writer.WriteValue(value.Name);
}
else
{
writer.WriteStartObject();
writer.WritePropertyName("name");
writer.WriteValue(value.Name);
writer.WritePropertyName("@language");
writer.WriteValue(value.Language);
writer.WriteEndObject();
}
}
}
}
77 changes: 77 additions & 0 deletions Source/Schema.NET/JsonLdContext.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
namespace Schema.NET
{
using System;
using System.Runtime.Serialization;

/// <summary>
/// The @context for a JSON-LD document.
/// See https://w3c.github.io/json-ld-syntax
/// </summary>
public class JsonLdContext : IEquatable<JsonLdContext>
{
/// <summary>
/// Gets or sets the name.
/// </summary>
[DataMember(Name = "name", Order = 0)]
public string Name { get; set; } = "http://schema.org";

/// <summary>
/// Gets or sets the language.
/// </summary>
[DataMember(Name = "@language", Order = 1)]
public string Language { get; set; }

/// <summary>
/// Performs an implicit conversion from <see cref="JsonLdContext"/> to <see cref="string"/>.
/// </summary>
/// <param name="context">The context.</param>
/// <returns>The result of the conversion.</returns>
public static implicit operator string(JsonLdContext context) => context.Name;

/// <summary>
/// Implements the operator ==.
/// </summary>
/// <param name="left">The left.</param>
/// <param name="right">The right.</param>
/// <returns>
/// The result of the operator.
/// </returns>
public static bool operator ==(JsonLdContext left, JsonLdContext right) => left.Equals(right);

/// <summary>
/// Implements the operator !=.
/// </summary>
/// <param name="left">The left.</param>
/// <param name="right">The right.</param>
/// <returns>
/// The result of the operator.
/// </returns>
public static bool operator !=(JsonLdContext left, JsonLdContext right) => !(left == right);

/// <inheritdoc />
public bool Equals(JsonLdContext other)
{
if (other is null)
{
return false;
}

if (object.ReferenceEquals(this, other))
{
return true;
}

return this.Name == other.Name &&
this.Language == other.Language;
}

/// <inheritdoc />
public override bool Equals(object obj) => this.Equals(obj as JsonLdContext);

/// <inheritdoc />
public override int GetHashCode() => HashCode.Of(this.Name).And(this.Language);

/// <inheritdoc />
public override string ToString() => this.Name;
}
}
30 changes: 16 additions & 14 deletions Source/Schema.NET/JsonLdObject.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
namespace Schema.NET
namespace Schema.NET
{
using System;
using System.Runtime.Serialization;

using System.Runtime.Serialization;
using Newtonsoft.Json;

/// <summary>
/// The base object
/// The base JSON-LD object.
/// See https://json-ld.org/spec/latest/json-ld
/// </summary>
[DataContract]
public class JsonLdObject
{
/// <summary>
/// Gets or sets the context used to define the short-hand names that are used throughout a JSON-LD document.
/// Gets the context used to define the short-hand names that are used throughout a JSON-LD document.
/// These short-hand names are called terms and help developers to express specific identifiers in a compact
/// manner.
/// When two people communicate with one another, the conversation takes place in a shared environment,
Expand All @@ -22,8 +23,16 @@ public class JsonLdObject
/// Simply speaking, a context is used to map terms to IRIs. Terms are case sensitive and any valid string that
/// is not a reserved JSON-LD keyword can be used as a term.
/// </summary>
[DataMember(Name = "@context", Order = 0)]
public virtual string Context { get; }
[DataMember(Name = "@context", Order = 0)]
[JsonConverter(typeof(ContextJsonConverter))]
public virtual JsonLdContext Context { get; internal set; } = new JsonLdContext();

/// <summary>
/// Gets or sets the type, used to uniquely identify things that are being described in the document with IRIs
/// or blank node identifiers.
/// </summary>
[DataMember(Name = "@type", Order = 1)]
public virtual string Type { get; }

/// <summary>
/// Gets or sets the identifier used to uniquely identify things that are being described in the document with
Expand All @@ -35,12 +44,5 @@ public class JsonLdObject
/// </summary>
[DataMember(Name = "@id", Order = 2)]
public virtual Uri Id { get; set; }

/// <summary>
/// Gets or sets the type, used to uniquely identify things that are being described in the document with IRIs
/// or blank node identifiers.
/// </summary>
[DataMember(Name = "@type", Order = 1)]
public virtual string Type { get; }
}
}
2 changes: 1 addition & 1 deletion Source/Schema.NET/Schema.NET.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
<ItemGroup Label="Package References">
<PackageReference Include="Microsoft.CodeAnalysis.FxCopAnalyzers" PrivateAssets="all" Version="2.9.2" />
<!-- See https://github.com/Microsoft/dotnet/tree/master/releases/reference-assemblies -->
<PackageReference Condition="'$(OS)' != 'Windows_NT'" Include="Microsoft.NETFramework.ReferenceAssemblies" PrivateAssets="All" Version="1.0.0-preview.2" />
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies" PrivateAssets="All" Version="1.0.0-preview.2" />
<PackageReference Include="Microsoft.SourceLink.GitHub" PrivateAssets="All" Version="1.0.0-beta2-19270-01" />
<PackageReference Include="Newtonsoft.Json" Version="12.0.2" />
<PackageReference Include="StyleCop.Analyzers" PrivateAssets="All" Version="1.1.118" />
Expand Down
2 changes: 1 addition & 1 deletion Source/Schema.NET/ValuesJsonConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace Schema.NET
using Newtonsoft.Json.Linq;

/// <summary>
/// Converts a <see cref="IValues"/> object to JSON.
/// Converts a <see cref="IValues"/> object to and from JSON.
/// </summary>
/// <seealso cref="JsonConverter" />
public class ValuesJsonConverter : JsonConverter
Expand Down
8 changes: 1 addition & 7 deletions Source/Schema.NET/core/Thing.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace Schema.NET
namespace Schema.NET
{
using System;
using System.Runtime.Serialization;
Expand Down Expand Up @@ -76,12 +76,6 @@ public partial interface IThing
[DataContract]
public partial class Thing : IThing
{
/// <summary>
/// Gets the context for the object, specifying that it comes from schema.org.
/// </summary>
[DataMember(Name = "@context", Order = 0)]
public override string Context => "http://schema.org";

/// <summary>
/// Gets the name of the type as specified by schema.org.
/// </summary>
Expand Down
63 changes: 63 additions & 0 deletions Tests/Schema.NET.Test/ContextJsonConverterTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
namespace Schema.NET.Test
{
using Newtonsoft.Json;
using Xunit;

public class ContextJsonConverterTest
{
[Fact]
public void ReadJson_StringContext_ContextHasName()
{
var json = "{\"@context\":\"foo\",\"@type\":\"Thing\"}";

var thing = JsonConvert.DeserializeObject<Thing>(json);

Assert.NotNull(thing.Context);
Assert.Equal("foo", thing.Context.Name);
Assert.Null(thing.Context.Language);
}

[Fact]
public void ReadJson_ObjectContextWithName_ContextHasName()
{
var json = "{\"@context\":{\"name\":\"foo\"},\"@type\":\"Thing\"}";

var thing = JsonConvert.DeserializeObject<Thing>(json);

Assert.NotNull(thing.Context);
Assert.Equal("foo", thing.Context.Name);
Assert.Null(thing.Context.Language);
}

[Fact]
public void ReadJson_ObjectContextWithNameAndLanguage_ContextHasNameAndLanguage()
{
var json = "{\"@context\":{\"name\":\"foo\",\"@language\":\"en\"},\"@type\":\"Thing\"}";

var thing = JsonConvert.DeserializeObject<Thing>(json);

Assert.NotNull(thing.Context);
Assert.Equal("foo", thing.Context.Name);
Assert.Equal("en", thing.Context.Language);
}

[Fact]
public void WriteJson_StringContext_ContextHasName()
{
var json = new Thing().ToString();

Assert.Equal("{\"@context\":\"http://schema.org\",\"@type\":\"Thing\"}", json);
}

[Fact]
public void WriteJson_ObjectContextWithLanguage_ContextHasName()
{
var thing = new Thing();
thing.Context.Language = "en";

var json = thing.ToString();

Assert.Equal("{\"@context\":{\"name\":\"http://schema.org\",\"@language\":\"en\"},\"@type\":\"Thing\"}", json);
}
}
}
67 changes: 67 additions & 0 deletions Tests/Schema.NET.Test/JsonLdContextTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
namespace Schema.NET.Test
{
using System.Collections.Generic;
using Xunit;

public class JsonLdContextTest
{
public static IEnumerable<object[]> EqualContexts => new List<object[]>
{
new object[] { new JsonLdContext(), new JsonLdContext() },
new object[] { new JsonLdContext() { Name = "a" }, new JsonLdContext() { Name = "a" } },
new object[]
{
new JsonLdContext() { Name = "a", Language = "b" },
new JsonLdContext() { Name = "a", Language = "b" },
},
};

public static IEnumerable<object[]> NotEqualContexts => new List<object[]>
{
new object[] { new JsonLdContext(), null },
new object[] { new JsonLdContext(), new JsonLdContext() { Name = "a" } },
new object[] { new JsonLdContext() { Name = "a" }, new JsonLdContext() },
new object[] { new JsonLdContext() { Name = "a" }, new JsonLdContext() { Name = "b" } },
new object[]
{
new JsonLdContext() { Name = "a", Language = "b" },
new JsonLdContext() { Name = "a", Language = "c" },
},
};

public static IEnumerable<object[]> ToStringContexts => new List<object[]>
{
new object[] { new JsonLdContext(), "http://schema.org" },
new object[] { new JsonLdContext() { Name = "a" }, "a" },
};

[Theory]
[MemberData(nameof(EqualContexts))]
public void Equals_IsEqual_ReturnsTrue(JsonLdContext a, JsonLdContext b) => Assert.True(a.Equals(b));

[Theory]
[MemberData(nameof(NotEqualContexts))]
public void Equals_IsNotEqual_ReturnsFalse(JsonLdContext a, JsonLdContext b) => Assert.False(a.Equals(b));

[Theory]
[MemberData(nameof(EqualContexts))]
public void EqualsOperator_IsEqual_ReturnsTrue(JsonLdContext a, JsonLdContext b) => Assert.True(a == b);

[Theory]
[MemberData(nameof(NotEqualContexts))]
public void EqualsOperator_IsNotEqual_ReturnsFalse(JsonLdContext a, JsonLdContext b) => Assert.False(a == b);

[Theory]
[MemberData(nameof(EqualContexts))]
public void NotEqualsOperator_IsEqual_ReturnsFalse(JsonLdContext a, JsonLdContext b) => Assert.False(a != b);

[Theory]
[MemberData(nameof(NotEqualContexts))]
public void NotEqualsOperator_IsNotEqual_ReturnsTrue(JsonLdContext a, JsonLdContext b) => Assert.True(a != b);

[Theory]
[MemberData(nameof(ToStringContexts))]
public void ToString_(JsonLdContext context, string expectedValue) =>
Assert.Equal(expectedValue, context.ToString());
}
}