Code Monkey home page Code Monkey logo

schema.net's Introduction

Schema.NET Banner

Schema.NET NuGet Package Schema.NET Azure Artifacts Package Schema.NET NuGet Package Downloads Twitter URL Twitter Follow

Schema.org objects turned into strongly typed C# POCO classes for use in .NET. All classes can be serialized into JSON/JSON-LD and XML, typically used to represent structured data in the head section of html page.

Simple Example

var website = new WebSite()
{
    AlternateName = "An Alternative Name",
    Name = "Your Site Name",
    Url = new Uri("https://example.com")
};
var jsonLd = website.ToString();

The code above outputs the following JSON-LD:

{
    "@context":"https://schema.org",
    "@type":"WebSite",
    "alternateName":"An Alternative Name",
    "name":"Your Site Name",
    "url":"https://example.com"
}

If writing the result into a <script> element, be sure to use the .ToHtmlEscapedString() method instead to avoid exposing your website to a Cross-Site Scripting attack. See the example below.

What is Schema.org?

schema.org defines a set of standard classes and their properties for objects and services in the real world. This machine readable format is a common standard used across the web for describing things.

Where is Schema.org Used?

Websites

Websites can define Structured Data in the head section of their html to enable search engines to show richer information in their search results. Here is an example of how Google can display extended metadata about your site in it's search results.

Google Logo Structured Data Example

Using structured data in html requires the use of a script tag with a MIME type of application/ld+json like so:

<script type="application/ld+json">
{
  "@context": "https://schema.org",
  "@type": "Organization",
  "url": "https://www.example.com",
  "name": "Unlimited Ball Bearings Corp.",
  "contactPoint": {
    "@type": "ContactPoint",
    "telephone": "+1-401-555-1212",
    "contactType": "Customer service"
  }
}
</script>
Important Security Notice

When serializing the result for a website's <script> tag, you should use the alternate .ToHtmlEscapedString() to avoid exposing yourself to a Cross-Site Scripting (XSS) vulnerability if some of the properties in your schema have been set from untrusted sources. Usage in an ASP.NET MVC project might look like this:

<script type="application/ld+json">
    @Html.Raw(Model.Schema.ToHtmlEscapedString())
</script>

Windows UWP Sharing

Windows UWP apps let you share data using schema.org classes. Here is an example showing how to share metadata about a book.

Classes & Properties

schema.org defines classes and properties, where each property can have a single value or an array of multiple values. Additionally, properties can have multiple types e.g. an Address property could have a type of string or a type of PostalAddress which has it's own properties such as StreetAddress or PostalCode which breaks up an address into it's constituent parts.

To facilitate this Schema.NET uses some clever C# generics and implicit type conversions so that setting a single or multiple values is possible and that setting a string or PostalAddress is also possible:

// Single string address
var organization = new Organization()
{
    Address = "123 Old Kent Road E10 6RL"
};

// Multiple string addresses
var organization = new Organization()
{
    Address = new List<string>()
    { 
        "123 Old Kent Road E10 6RL",
        "456 Finsbury Park Road SW1 2JS"
    }
};

// Single PostalAddress address
var organization = new Organization()
{
    Address = new PostalAddress()
    {
        StreetAddress = "123 Old Kent Road",
        PostalCode = "E10 6RL"
    }
};

// Multiple PostalAddress addresses
var organization = new Organization()
{
    Address = new List<PostalAddress>()
    {
        new PostalAddress()
        {
            StreetAddress = "123 Old Kent Road",
            PostalCode = "E10 6RL"
        },
        new PostalAddress()
        {
            StreetAddress = "456 Finsbury Park Road",
            PostalCode = "SW1 2JS"
        }
    }
};

// Mixed Author types
var book = new Book()
{
    Author = new List<object>()
    {
        new Organization() { Name = "Penguin" },
        new Person() { Name = "J.D. Salinger" }
    }
};

// Deconstruct a property containing mixed types
if (book.Author.HasValue)
{
    var (organisations, people) = book.Author.Value;
}

This magic is all carried out using implicit conversion operators in the OneOrMany<T>, Values<T1, T2>, Values<T1, T2, T3> and Values<T1, T2, T3, T4> types. These types are all structs for best performance too.

More Examples

For more examples and actual running code samples, take a look at the unit tests in the project source code.

Schema.NET.Pending

There are many pending types on schema.org which are not yet fully formed and ready for production. If you need to use these, you can install the Schema.NET.Pending NuGet package instead of Schema.NET. This package contains all released schema types as well as all pending types.

Schema.NET.Pending NuGet Package Schema.NET.Pending Azure Artifacts Package Schema.NET.Pending NuGet Package Downloads

Continuous Integration

Name Operating System Status History
Azure Pipelines Ubuntu Azure Pipelines Ubuntu Build Status
Azure Pipelines Mac Azure Pipelines Mac Build Status
Azure Pipelines Windows Azure Pipelines Windows Build Status
Azure Pipelines Overall Azure Pipelines Overall Build Status Azure DevOps Build History
GitHub Actions Ubuntu, Mac & Windows GitHub Actions Status GitHub Actions Build History
AppVeyor Ubuntu, Mac & Windows AppVeyor Build Status AppVeyor Build History

Contributions and Thanks

Please view the contributing guide for more information.

  • kirkone - CI reads .NET Core version from new global.json file.
  • Turnerj - Added System.Text.Json support, Had all types implement IEquatable<T> GetHashCode and added extra unit tests and bug fixes.
  • shervinw - Added better null value handling for structs.
  • kirk-marple - Refactoring JSON serialization to be more efficient.
  • nickevansuk - Adding better null value handling and use HTTPS instead of HTTP.
  • MEmanuelsson - Added support for the schema.org Date type without time.
  • halovanic - For adding interfaces to Schema.NET types for greater flexibility.
  • AndreSteenbergen - For enabling the tool to work on linux.
  • benmccallum - For adding XSS vlnerability protection.
  • psampaio - Added deserialization support and unit tests.
  • icunningham88 - Improved a test.

schema.net's People

Contributors

andresteenbergen avatar benmccallum avatar csdecrypt avatar dependabot-preview[bot] avatar dependabot-support avatar dependabot[bot] avatar dermotblairca avatar icunningham88 avatar imgbot[bot] avatar kirk-marple avatar kirkone avatar memanuelsson avatar nickevansuk avatar rehansaeed avatar renovate-bot avatar renovate[bot] avatar shervinw avatar shravan2x avatar slang25 avatar turnerj avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

schema.net's Issues

JsonConvert.SerializeObject not writing out enums as string values

I realized there appears to be a bug in using JsonConvert.SerializeObject vs ToString. In CarTest.cs, if you look at 'this.car', and compare, the outputs are different.

ToString:
"availability": "http://schema.org/InStock",
SerializeObject:
"availability": 1,

For objects with enums, which are serialized using SerializeObject, the ValuesJsonConverter.cs will fail upon parsing the enum (expecting a string not an integer).

I've tested that changing each enum class to be in this form solves the issue, and SerializeObject will write out the values upon serialization:

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

/// <summary>
/// A list of possible product availability options.
/// </summary>
[JsonConverter(typeof(StringEnumConverter))]
public enum ItemAvailability

I've fixed the tool that generates these:
.\Source\Schema.NET.Tool\ViewModels\Enumeration.cs

But will also make ValuesJsonConverter work for deserializing both the string and the integer representation.

Filing a PR shortly.

(Also, I believe this is what #25 was about.)

Using Schema.NET in ASP.NET Core controllers in model binding

Hi!

I was wondering if you would have advice on how to use this interesting library in ASP.NET Core controllers so that roughly the following would work:

[HttpPost("[action]")]
public IActionResult Test([FromBody] Thing thing)
{
    var e = (Person)thing;
    return Accepted(new Uri("https://wwww.WhereToAskForResults.com"));
}

That is, accept JSON-LD data via a base classes. Or put other way, if I have a JSON document, say like at https://jsonld.com/person/, how could it be deserialized to a .NET object of Person.

Support `DateOnly` and `TimeOnly` fields

Agreed. I have no idea how we're going to support DateOnly and have supports for the targets we do without a lot of #if statements.

Maybe... if we had an intermediary struct for dates, we could keep all the logic there rather than have a mix of the logic across the code base? Could implicitly convert between it and whatever the user intended. (Though this is also kinda messy)

Originally posted by @Turnerj in #100 (comment)

Cloning Schema.NET object

I have a MusicAlbum, which looks like below, and had a use case where I wanted to create a duplicate object instance.

I tried using JsonConvert.SerializeObject/DeserializeObject, but I'm getting a cast exception in Newtonsoft.Json: Could not cast or convert from System.String to Schema.NET.PropertyValue.

Any idea what could be causing this?

{ {
"@context": "http://schema.org",
"@type": "MusicAlbum",
"name": "Hail To the Thief",
"identifier": "1oW3v5Har9mvXnGk0x4fHm",
"image": {
"@type": "ImageObject",
"contentUrl": "https://i.scdn.co/image/5ded47fd3d05325dd0faaf4619481e1f25a21ec7"
},
"url": "https://open.spotify.com/album/1oW3v5Har9mvXnGk0x4fHm",
"datePublished": "2003-01-01",
"offers": {
"@type": "Offer",
"gtin12": "634904078560"
},
"numTracks": 14,
"albumRelease": {
"@type": "MusicRelease",
"recordLabel": {
"@type": "Organization",
"name": "XL Recordings"
}
},
"byArtist": {
"@type": "MusicGroup",
"name": "Radiohead",
"identifier": "4Z8W4fKeB5YxbusRsdQVPb"
}
}
}

hasMap is for microdata only

Which schema.org object is this about if any?

According to the spec, hasMap is for microdata only. Probably shouldn't be included in JSON+LD output but currently, it is.

{
  "@context": "http://schema.org",
  "@type": "LocalBusiness",
  "name": "Schema.NET.OneOrMany`1[System.String] Shropshire",
  "description": "",
  "image": "https://www.bluebirdcare.co.uk/getmedia/4d3f2336-0cf7-4ad0-bd4a-276b71e9d284/bluebird-logo-blue.png?width=160&height=98&ext=.png",
  "url": "https://www.bluebirdcare.co.uk/shropshire",
  "address": "3 The Parade\r\n Lansdowne Road\r\n Bayston Hill\r\nShrewsbury England SY3 0HT",
  "award": [],
  "contactPoint": [
    {
      "@type": "ContactPoint",
      "contactType": "customer support",
      "email": "[email protected]",
      "telephone": "+44 1743 874343"
    },
    {
      "@type": "ContactPoint",
      "url": "https://www.bluebirdcare.co.uk/shropshire/careers",
      "contactType": "customer support",
      "email": "[email protected]"
    }
  ],
  "hasMap": "https://www.google.com/maps/place/3%20The%20Parade%0D%0A%20Lansdowne%20Road%0D%0A%20Bayston%20Hill%0D%0AShrewsbury%20England%20SY3%200HT",
  "logo": "https://www.bluebirdcare.co.uk/getmedia/4d3f2336-0cf7-4ad0-bd4a-276b71e9d284/bluebird-logo-blue.png?width=160&height=98&ext=.png",
  "memberOf": {
    "@type": "Organization",
    "name": "UKHCA",
    "description": "United Kingdom Homecare Association's mission is to promote high quality, sustainable homecare so people can continue to live at home and in their community.",
    "url": "https://www.ukhca.co.uk/",
    "logo": "https://www.ukhca.co.uk/images/ukhca.png"
  },
  "parentOrganization": {
    "@type": "Organization",
    "name": "Bluebird Care",
    "description": "Bluebird Care provides the highest quality of home care, leading the field in customer service.",
    "sameAs": [
      "https://www.facebook.com/BluebirdCareUK/",
      "https://twitter.com/BluebirdCare",
      "https://www.linkedin.com/company/bluebird-care",
      "https://www.instagram.com/bluebirdcareuk/"
    ],
    "url": "https://www.bluebirdcare.co.uk/",
    "address": "Bluebird Care (Franchise Support Centre), Charles House, Charles Street, Petersfield, Hampshire, GU32 3EH",
    "award": [
      "Award2",
      "Award3",
      "Award1"
    ],
    "contactPoint": [
      {
        "@type": "ContactPoint",
        "contactType": "customer support",
        "email": "[email protected]",
        "telephone": "+44 1730 260 026"
      },
      {
        "@type": "ContactPoint",
        "contactType": "technical support",
        "telephone": "+44 1730 260 026"
      },
      {
        "@type": "ContactPoint",
        "url": "https://www.bluebirdcare.co.uk/careers",
        "contactType": "customer support"
      }
    ],
    "department": {
      "@type": "Organization",
      "name": "Head office",
      "address": "Bluebird Care (Franchise Support Centre), Charles House, Charles Street, Petersfield, Hampshire, GU32 3EH",
      "logo": "https://www.bluebirdcare.co.uk/getmedia/4d3f2336-0cf7-4ad0-bd4a-276b71e9d284/bluebird-logo-blue.png?width=160&height=98&ext=.png"
    },
    "logo": "https://www.bluebirdcare.co.uk/getmedia/4d3f2336-0cf7-4ad0-bd4a-276b71e9d284/bluebird-logo-blue.png?width=160&height=98&ext=.png",
    "memberOf": {
      "@type": "Organization",
      "name": "UKHCA",
      "description": "United Kingdom Homecare Association's mission is to promote high quality, sustainable homecare so people can continue to live at home and in their community.",
      "url": "https://www.ukhca.co.uk/",
      "logo": "https://www.ukhca.co.uk/images/ukhca.png"
    }
  },
  "telephone": "+44 1743 874343"
}

BreadcrumbList itemListElement listitem with string item value

Is it possible to produce JSON like this using this library ?

      "@context": "https://schema.org",
      "@type": "BreadcrumbList",
      "itemListElement": [{
        "@type": "ListItem",
        "position": 1,
        "name": "Books",
        "item": "https://example.com/books"
      },{
        "@type": "ListItem",
        "position": 2,
        "name": "Science Fiction",
        "item": "https://example.com/books/sciencefiction"
      },{
        "@type": "ListItem",
        "position": 3,
        "name": "Award Winners"
      }]
    }

I tried but I get a compiler error when assigning a string to item

OneOrMany handling of Value types vs Reference types with default values

I've been looking at further performance and allocation optimisations - one that I have been messing with is making OneOrMany only internally hold an array rather than an array and a single item.

While for the most part this is just an implementation change (no API changes), it did show a few things, that are strange to me, with how OneOrMany works.

OneOrMany won't store a single null value (Count == 0) but will allow multiple null values (Count > 1). This is strange behaviour though is backed up in the tests like in the CarTest.

https://github.com/RehanSaeed/Schema.NET/blob/master/Tests/Schema.NET.Test/core/CarTest.cs#L20

I feel that it should be consistent - if any null values (or empty strings) are provided, they are ignored/not added internally to the OneOrMany. This is what the implicit conversion logic does but I think the constructor should be handling that instead. I would likely inline the implicit conversion logic to the constructor(s) instead.

The other thing I found is if OneOrMany is a value type, it always has a value. I understand this from the perspective that int etc can't be null but at the same time, it doesn't make sense to me why a default OneOrMany<int> actually has anything at all. I'm not sure if it is like this due to the previous implementation (by holding a single item value of T which would not be null for value types) or if it was intentional.

This is what I've currently built (builds upon changes in #109): https://gist.github.com/Turnerj/6d0400887912f454ef2be033c682ff4e#file-oneormany-cs

Really this issue is just to gauge your thoughts on such a change? Various tests would need updating as a number play on the logic that something like OneOrMany<int> should always have a value. (I can work to keep that logic but I figure while I'm doing this update, I might find out if it is even necessary)

I'm happy to do the changes - probably in #109 or otherwise after that has merged. Right now it looks like a 3% allocation improvement (in the Book benchmark) though I think there is probably more I can get out of it.

Support Serialize/Deserialize of new Schema.org Objects

New objects that don't exist in the Schema.NET library should still deserialize to a Thing successfully.

  1. Write a unit test to confirm that this does or doesn't happen already.
  2. Fix it if the unit test confirms that it is not working.
  3. Think about how you could write your own custom objects and provide them to the Schema.NET serializer.

Setting an "incomplete" date for a Date/DateTime property

I am trying to set just the Year for CreativeWork,dateCreated property. But since in Schema.NET, the dateCreated is of DateTimeOffset data type, it is impossible to do so.

Based on Schema.org/Date, the date format should follow ISO8601 (http://en.wikipedia.org/wiki/ISO_8601), which basically, allows "yyyy" format.

“ISO 8601 prescribes, as a minimum, a four-digit year [YYYY]…”

The same can also be referenced in https://www.w3.org/TR/NOTE-datetime.

Any help would be greatly appreciated.

TimeSpan for OpeningHours?

I was wondering why implementing the Opens and Closes attributes of OpeningHoursSpecification as a TimeSpan, it seems counterIntuitive given this data is supposed to represent an hour when a business or place opens or closes.

As a result, I don't know how to implement it in my project, I thought it would be more logical to use a DateTime.

Would you have some explanation that would help me understand it better and use it correctly?

Thanks in advance

Special structs for Date and DateTime

I raised this issue (schemaorg/schemaorg#2240) on the schemaorg github repo yesterday regarding how to handle Date which only consists of a year in the Schema.NET implementation of schemaorg. Following the comment from RichardWallis I believe it would be a good idea to create special structs to handle Date and DateTime in the schemas where these are applicable since DateTimeOffset (now being used) always contains a complete date and time. Any thoughts around this?

VS2019 builds on AppVeyor don't fail properly

Basically when a build fails on AppVeyor under Ubuntu, it correctly exits with an error. When a build fails on AppVeyor under the VS2019 build image, it doesn't and continues through to the end which leads to AppVeyor marking the build as successful.
https://ci.appveyor.com/project/RehanSaeed/schema-net/builds/32492091/job/t9wkbp4s8dbk23is#L85

This is a fairly low-priority bug and in most cases, if a build fails on Windows it likely fails on other OSes. It also is only an issue on AppVeyor as Azure DevOps works fine: https://dev.azure.com/schema-net/Schema.NET/_build/results?buildId=695&view=logs&j=c7dcf16a-b484-548d-e1f9-8e1c62e0ef67&t=9fb06c61-dd1f-57a6-70e3-8d4e32391b2b&l=79

It bugs me just enough to raise an issue about it... I'll try and get it sorted sometime in the future.

Support Deserializing @language inside @context Object

I get an exception from JsonConvert when I do this. The result is null.
Newtonsoft.Json.JsonConvert.DeserializeObject(Of Schema.NET.LocalBusiness)(json)

This is the exception:

Newtonsoft.Json.JsonReaderException: 'Unexpected character encountered while parsing value: [. Path '@context', line 4, position 16.'

This is the json I'm working with... Is there a syntax error somewhere?

{
  "@context" : [ "http://schema.org", {
    "@language" : "it"
  } ],
  "@type" : "LocalBusiness",
  "name" : "Mario Rossi",
  "url" : "https://example.com/mario-rossi-srl",
  "@id" : "https://example.com/mario-rossi-srl",
  "legalName" : "Mario Rossi s.r.l.",
  "currenciesAccepted" : "EUR",
  "address" : {
    "@type" : "PostalAddress",
    "addressLocality" : "Venezia",
    "addressRegion" : "VN",
    "postalCode" : "00334",
    "streetAddress" : "10, Piazza Grande"
  },
  "contactPoint" : [ {
    "@type" : "ContactPoint",
    "contactType" : "customer service",
    "telephone" : "+393332234666"
  } ],
  "telephone" : "+393332234666"
}

Parse JSON-LD into C# object

Hi,

is it possible to parse JSON-LD data into a C# object. According to the documentation, it seems that the conversion is only the other way around from a C# object to JSON-LD data.

Potential XSS vulnerability

I think that a lot of people in the ASP.NET MVC world would do something like this to get their schema rendered.

<script type="application/ld+json">
    @Model.myThing.ToString();
</script>

Problem is with Json.Convert's default settings, that opens up an XSS vulnerability if the data put in a thing's property was untrusted. e.g. a business name on your website could be user-supplied by that business, and they could make their business name </script><script>alert('gotcha');</script>.

I think it would be addressed by updating the default Serialization settings in Thing.cs to include StringEscapeHandling = StringEscapeHandling.EscapeHtml, but this isn't my area of expertise. That also might be a breaking change if HTML is allowed in any schema properties?

What do you think? Just opening it up for discussion as trying to avoid this in my own project.

Can't deserialize response from NHS Search which says it complies with schema.org

            var content = response.Content;
            var srp = JsonConvert.DeserializeObject<Schema.NET.SearchResultsPage>(content);

Newtonsoft.Json.JsonSerializationException
HResult=0x80131500
Message=Error setting value to 'Breadcrumb' on 'Schema.NET.SearchResultsPage'.
Source=Newtonsoft.Json
StackTrace:
at Newtonsoft.Json.Serialization.DynamicValueProvider.SetValue(Object target, Object value)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.SetPropertyValue(JsonProperty property, JsonConverter propertyConverter, JsonContainerContract containerContract, JsonProperty containerProperty, JsonReader reader, Object target)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.PopulateObject(Object newObject, JsonReader reader, JsonObjectContract contract, JsonProperty member, String id)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue)
at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize(JsonReader reader, Type objectType, Boolean checkAdditionalContent)
at Newtonsoft.Json.JsonSerializer.DeserializeInternal(JsonReader reader, Type objectType)
at Newtonsoft.Json.JsonConvert.DeserializeObject(String value, Type type, JsonSerializerSettings settings)
at Newtonsoft.Json.JsonConvert.DeserializeObject[T](String value, JsonSerializerSettings settings)

To Reproduce

Register for API access at https://developer.api.nhs.uk/documentation/content-api?filter=news
Call the "Behind The Headline" / "All News" API
Try to deserialize the result as above.
(or do the same with the sample response attached)

Expected behaviour

The response should deserialize correctly without an error.

Schema Objects

SearchResultPage

ExampleBehindTheHeadlinesResponse.txt

Implicit conversions in 4.0

First off, thanks for making the new release, it cleaned up a lot of my messy data access code.

I think I've found a few edge cases where this still doesn't work, though.

For example, this should work, but gives the error below:

            IGeoCoordinates geo = place.Geo;

Cannot implicitly convert type 'Schema.NET.Values<Schema.NET.IGeoCoordinates, Schema.NET.IGeoShape>?' to 'Schema.NET.IGeoCoordinates'

I need to keep my old code like this, for it to compile:

            IGeoCoordinates geo = place.Geo.Value.Value1.FirstOrDefault();

I've found similar problems:
IPostalAddress address = musicVenue.Address;
IMusicGroup artist = musicAlbum.ByArtist;
IMusicGroup artist = musicRecording.ByArtist;

Wrong type for Book.Author ("Persona" become an "Organization") after deserialization

Author deserialization issue

Just run into situation:

for Book I have a list of Author type of Person

...
"author": [
        {
            "@type": "Person",
            "name": "SomeName",
            "description": "SomeDescription.md",
            "image": "SomeImage",
            "url": "https://someUrl.me",
            "email": "[email protected]",
            "jobTitle": "CEO SomeCompany Solutions"
        },
        {
            "@type": "Person",
            "name": "Иван Васильевич",
            "image": "Images/Иван Васильевич.jpg",
            "email": "[email protected]",
            "jobTitle": "просто Царь"
        }
    ]
...

the way I`m deserialize:

public static Book GetMetadata(string path)
        {
            var file = Path.Combine(path, FileNames.Metadata);
            if (File.Exists(file))
            {
                var json = File.ReadAllText(file);
                Book bookMetadata = JsonConvert.DeserializeObject<Book>(json) as Book;
                return bookMetadata;
            }
            else
                throw new ArgumentNullException("Metadata file is missing.");
        }

but after deserialization of my "schema.json" into c# class I got field "Author" type of Organization. Any other fields like "JobTitle" are ignored.

image

OneOrMany ctor to accept null?

Just ran into a situation where I'm passing in null into a property that's OneOrMany<T> and the ctor(T item) throws an exception.

Just wondering whether this is necessary or we can allow null to be set and handled internally. Otherwise code like below becomes much more complicated as I need to null-check every assignment and can't use object initialization, instead need to instantiate then assign properties if not null.

            return new LocalBusiness
            {
                Name = Name,
                Image = Image,
                PriceRange = "$$",
                Address = new PostalAddress
                {
                    StreetAddress = Address,
                    AddressLocality = Suburb,
                    AddressRegion = State?.ToUpper(),
                    PostalCode = Postcode
                }
            };

What do you think? Would it be possible given all the generics/internals in play here?

As is the behaviour for other properties that allow null, I'd expect if OneOrMany<T> was set to null to not render out to JSON. Or I guess respect the JsonSerializerSettings null handling we now have an overload for. Assuming the value returned is null that should all work ootb.

Deserialize fails for Recipe.RecipeInstructions

Which schema.org object is this about if any?

Recipe
https://schema.org/Recipe

Deserializing a recipe fails when changing recipeInstructions from a string to a List.

Snippet from RecipeTest.cs:

var recipe = new Recipe()
        {
            Name = "Grandma's Holiday Apple Pie",
            // RecipeInstructions = "1. Cut and peel apples...",
            RecipeInstructions = new List<ICreativeWork>()
            {
                new HowToStep { Text = "Do something" },
                new HowToStep { Text = "Do something else" }
            }
        };

Corresponding json snippet in RecipeTest.cs:

"\"recipeInstructions\":[" +
                "{\"@type\":\"HowToStep\",\"text\":\"Do something\"}," +
                "{\"@type\":\"HowToStep\",\"text\":\"Do something else\"}" +
            "]," +

Is deserialization working for all types?

public Values<ICreativeWork, IItemList, string>? RecipeInstructions { get; set; }

ToString() and ToHtmlEscapedString() result in a single line

First, thanks for the library! Shaved a good amount of time on this project I'm on!

This is only an annoyance and I may be missing something on my end, but when I dump out the JobPosting object in a Razor view:

        <script type="application/ld+json">
            @Html.Raw(jobJSON.ToString().Replace("\\r\\n", ""))
        </script>

I end up everything in a single line:
{"@context":"https://schema.org","@type":"JobPosting","title":"Citrix Virtual Desktop Engineer","description":"

A global life insurance firm is hiring a desktop engineer. 

 

This is a wonderful opportunity to wo

Just makes it difficult to debug. Please let me know if there's a flag somewhere or something I can do to get formed json with line breaks. Thanks

The type 'System.Object' is defined in an assembly that is not referenced

I had a difficult time integrating this library into a .NET 4.7.2 / MVC 5 application, due to the following exception I was receiving on my cshtml page at runtime.

The type 'System.Object' is defined in an assembly that is not referenced. You must add a reference to assembly 'netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51'.

It turns out that is is due to the project specifying <TargetFrameworks>netstandard1.1;netstandard2.0</TargetFrameworks> instead of <TargetFrameworks>netstandard1.1;netstandard2.0;net452</TargetFrameworks>.

In a previous rejected pull request you mention:

This project supports netstandard1.1 and netstandard2.0 which means that .NET 4.5.2 is already supported.

Feel free to reopen if I've missed something.

Originally posted by @RehanSaeed in #27 (comment)

While this is technically true, it requires an unintuitive workaround in my web.config as follows:

<compilation debug="true" targetFramework="4.7.2">
  <assemblies>
    <add assembly="netstandard, Version=2.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51"/>
  </assemblies>
</compilation>

Which I finally found from this thread: dotnet/standard#542

Anyway, I just wanted to help out anyone else that may run into this issue in the future.

Upgrading to Schema.org Release 7.0 - Issues with extending primitives

On the 21st of January, the next version of Schema.org has been released. I was going to open a PR to upgrade to however there seems to be some issues with the tool that I'm not sure how to handle - some of the problem might actually be a bug from Schema.org but at this stage, let's just look at it in scope of this project.

There is a new type called PronounceableText. While this type is (apparently) pending, the schema tool doesn't see it as pending. Additionally though, this is a type that extends a primitive which doesn't seem supported. (Of note, PronounceableText itself isn't classified as a primitive even though it extends Text which is)

When running the tool, it trips this exception when processing PronounceableText:

var parentClass = classes.FirstOrDefault(x => x.Id == parentClassId);
if (parentClass is null)
{
throw new Exception(Resources.CheckThatNewPrimitiveTypeNotAdded);
}

In one way, if this type is pending it shouldn't even hit here. If it is technically marked correctly but the website is wrong saying it is pending, we need to work out how to handle types that extend primitives.

Should primitive types be "real" types in Schema.NET? For example, we could have a Text type (with no interface) and have it implicitly convert to/from string? That way, we could build PronounceableText on top of it? It should allow all our Values<> and OneOrMany<> implicit things to still work with concrete types etc. We'd probably want the primitive types to be struct though to help avoid additional allocations when dealing with numbers and dates (which would also likely follow this pattern).

I'm thinking unless we are going to ignore this primitive, we might need to do a bit of an overhaul of the schema tool.

What are your thoughts on this?

Add metadata for Schema.org Version

Describe the feature

I'm not 100% sure we actually get this from our data source but it would be nice having a program-accessible constant that refers to the Schema.org version that the code is currently using.

Source generator dependency issues

Background

When adding the source generator in #252, I stumbled across weird behaviour where I needed to specify additional dependencies that we didn't directly seem to need - in our case, this was System.Text.Encodings.Web. Source generators require some more verbose methods of specifying these NuGet packages too:

<ItemGroup Label="Package References">
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="3.9.0" />
<PackageReference Include="System.Text.Json" Version="5.0.1" GeneratePathProperty="true" PrivateAssets="all" />
<PackageReference Include="System.Text.Encodings.Web" Version="5.0.1" GeneratePathProperty="true" PrivateAssets="all" />
</ItemGroup>
<PropertyGroup>
<GetTargetPathDependsOn>$(GetTargetPathDependsOn);GetDependencyTargetPaths</GetTargetPathDependsOn>
</PropertyGroup>
<Target Name="GetDependencyTargetPaths">
<ItemGroup>
<TargetPathWithTargetPlatformMoniker Include="$(PKGSystem_Text_Json)\lib\netstandard2.0\System.Text.Json.dll" IncludeRuntimeDependency="false" />
<TargetPathWithTargetPlatformMoniker Include="$(PKGSystem_Text_Encodings_Web)\lib\netstandard2.0\System.Text.Encodings.Web.dll" IncludeRuntimeDependency="false" />
</ItemGroup>
</Target>

I thought this was the end of the problems - oh I was very wrong...

The Problem

Hitting the issue with requiring System.Text.Encodings.Web is small and not a big deal. The problem is (as briefly mentioned in #262) that needing to specify System.Text.Encodings.Web isn't a random issue - it is a dependency of System.Text.Json but as packages usually do, they can have many dependencies and their dependencies have dependencies.

The .NET runtime doesn't seem to care if an assembly is missing until it actually needs it which is the crux of our problem. Through the code paths in System.Text.Json, it invokes something in System.Text.Encodings.Web thus why it needed to be specified. When we upgraded to System.Text.Encodings.Web in #261 (updating from 5.0.0 to 5.0.1), that ended up being a breaking change for us.

Generator 'SchemaSourceGenerator' failed to initialize. It will not contribute to the output and compilation errors may occur as a result. Exception was of type 'FileNotFoundException' with message 'Could not load file or assembly
'System.Text.Encodings.Web, Version=5.0.0.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51' or one of its dependencies. The system cannot find the file specified.'

Weird how we didn't have any CI errors in #261 then right? Yeah it turns out when compiled within the realm of .NET Framework (eg. MSBuild or Visual Studio) this error occurs but not via dotnet build. In #262 I thought the issue was an environmental one for me as everything else CI-wise seemed good. I raised an issue about this with the Roslyn team via dotnet/roslyn#52017 however the issues is ours, not theirs.

Source generators need to specify all dependencies in the entire dependency tree. The reason I hit this after #261 is that something in moving to System.Text.Encodings.Web 5.0.1 invoked a new path internally to one of its dependencies. The error message doesn't say unfortunately but it is either a dependency on System.Memory or System.Buffers as those are the dependencies for 5.0.1.

As a fun aside, I will note that under .NET Standard 2.0 dependencies for System.Text.Encodings.Web, it added System.Buffers when moving to 5.0.1 - prior to that it only had a dependency on System.Memory

Getting back on track now, fixing this error for System.Text.Encodings.Web can be done by adding System.Memory and System.Buffers directly like I already have for System.Text.Encodings.Web - so far, so good. Because we should be specifying every dependency in the tree, we actually should be specifying:

  • Microsoft.Bcl.AsyncInterfaces, 5.0.0
  • System.Buffers, 4.5.1
  • System.Memory, 4.5.4
  • System.Numerics.Vectors, 4.5.0
  • System.Runtime.CompilerServices.Unsafe, 5.0.0
  • System.Text.Encodings.Web, 5.0.0
  • System.Threading.Tasks.Extensions, 4.5.4

All that just for supporting System.Text.Json BUT even then it isn't as easy as it seems. If any of those packages get new dependencies, we would need to add them too and we can only tell that we need to if we hit the issue. Because our CI doesn't hit the issue, it will be adhoc if we discover it.

Solutions

Solution A

Just specify all those dependencies in that verbose format I showed earlier - it would solve the current problem for local development.

Solution B

Build some general purpose MSBuild target that can take a more normal package reference list and add all that verbose markup and entire dependency tree itself.


I'm personally looking into how Solution B would work as it would be a good issue to solve for the .NET ecosystem.

Improving how the @context property is serialized

Describe the feature

Currently the @context property is always serialized. Using our SchemaSerializer class, we keep the outer @context property but we replace all inner @context properties by a StringBuilder.Replace call which means we allocate the whole JSON output as a string twice.

Ideally, we need a way to conditionally serialize the @context property only if it is the root object of serialization.

How to actually implement this (especially in a future System.Text.Json world) remains unknown however it should still be considered. Potentially if we can provide a custom converter for the root-level object that can output that property and for any nested properties, simply not pass that converter down - this may give us our desired effect.

Adding Helper/Utility Functionality (Merging, Clearing Empty, Value Type Promotion)

Describe the feature

There is a set of functionality that I'm working on that I think would be a good fit for the library as utilities for working with Schema objects in certain ways.

Merging
It would be useful to be able to merge appropriate objects and their properties together (where applicable) and use other known "ID" properties (eg. URL or Identifier properties, both path of IThing) to know whether they should merge.

Because at its core, every property can have one or many values, merging them isn't too difficult. We would probably want a way to provide custom type comparers though as people do extend schema types etc let alone for other examples (eg. maybe URLs are considered equal even if their query string is different).

Clearing Empty
This fits somewhat closely with the Merging one - being able to remove Schema objects with no values specifically defined would be a useful feature. This can be as simple as check the count on each property.

Value Type Promotion
This one is useful, especially prior to running any Merge logic - in many cases, a value can be represented by multiple types for a single property. For example, an image might be a Uri or it might be a ImageObject.

Value promotion would be a way to convert a new Uri() to an new ImageObject { Uri = theUri } as these two are functionally equivalent. In a form like this, it can make dealing with external data (where you don't control the consistency of it) a lot easier to deal with.

There may even be use for going the other way too (converting an ImageObject with only the Uri property set back to just a Uri type) - maybe for making the most size-efficient JSON - though personally I haven't needed to.


These features are useful for working with the Schema objects in different ways though at the same time, might not actually need to belong to the main library. This might be a good utility library like Schema.NET.Utilities or something - I'll leave that up to you.

Right now, I've got pretty "crappy" implementations of these in my current project (something that heavily relies on Schema.NET) and I don't know when I will be able to get better versions as a PR, this issue is to initially raise this as a point of discussion and get your thoughts on it and whether it would be worth having in the main library or in a utility library.

BusinessFunction enum missing values

Describe the bug

There are currently no values inside the BusinessFunction enum. When using the default value this results in an error.

I've seen this has been previously raised (#60) but because there's no open ticket I am creating one so I can fork and add a PR.

To Reproduce

Using the below code causes an error:

Offers = new Offer() { BusinessFunction = new OneOrMany<BusinessFunction?>(new BusinessFunction() { }), }

Expected behaviour

Enum has values as described at: https://schema.org/BusinessFunction

Might be as simple as adding this to the BusinessFunction Enum

   `/// <summary>
    /// Indicates that the value is Sell.
    /// This is the default value.
    /// </summary>
    [EnumMember(Value = "http://purl.org/goodrelations/v1#Sell")]
    Sell,

    /// <summary>
    /// Indicates that the value is Buy.
    /// </summary>
    [EnumMember(Value = "http://purl.org/goodrelations/v1#Buy")]
    Buy,

    /// <summary>
    /// Indicates that the value is ConstructionInstallation.
    /// </summary>
    [EnumMember(Value = "http://purl.org/goodrelations/v1#ConstructionInstallation")]
    ConstructionInstallation,

    /// <summary>
    /// Indicates that the value is ConstructionIDisposenstallation.
    /// </summary>
    [EnumMember(Value = "http://purl.org/goodrelations/v1#Dispose")]
    Dispose,

    /// <summary>
    /// Indicates that the value is LeaseOut.
    /// </summary>
    [EnumMember(Value = "http://purl.org/goodrelations/v1#LeaseOut")]
    LeaseOut,

    /// <summary>
    /// Indicates that the value is Maintain.
    /// </summary>
    [EnumMember(Value = "http://purl.org/goodrelations/v1#Maintain")]
    Maintain,

    /// <summary>
    /// Indicates that the value is ProvideService.
    /// </summary>
    [EnumMember(Value = "http://purl.org/goodrelations/v1#ProvideService")]
    ProvideService,

    /// <summary>
    /// Indicates that the value is Repair.
    /// </summary>
    [EnumMember(Value = "http://purl.org/goodrelations/v1#Repair")]
    Repair,`

But I haven't been able to fork and get the package to work in my project.

Schema Objects

Which schema.org object is this about if any?

https://schema.org/BusinessFunction

Inconsistent deserialization for OneOrMany properties on derived classes

Describe the bug

I have some properties of OneOrMany<T> that deserialize when they're single valued, but not when array valued; but others that deserialize fine in either situation.

To Reproduce

I'm working with three derived classes: the first extends PostalAddress with properties of type OneOrMany<IAdministrativeArea>, and is called ExtendedAddress; the second extends Thing with some basic tracking, and is called ExtendedThing; the third contains properties of both those types, and is called Project. Here's the relevant parts of each class:

public partial class ExtendedThing : Thing, IExtendedThing
{
		[DataMember(Name = "@type", Order = 1)]
		public override string Type => "ExtendedThing";
  // The tracking properties aren't relevant right now
}

public partial class ExtendedAddress : PostalAddress, IExtendedAddress
{
		[DataMember(Name = "@type", Order = 1)]
		public override string Type => "ExtendedAddress";
		[DataMember(Name = "addressCounty", Order = 506)]
		[JsonConverter(typeof(ValuesJsonConverter))]
		public OneOrMany<IAdministrativeArea> AddressCounty { set; get; }
}

public partial class Project : ExtendedThing, IProject
{
		[DataMember(Name = "@type", Order = 1)]
		public override string Type => "Project";
		[DataMember(Name = "affectedSite", Order = 206)]
		[JsonConverter(typeof(ValuesJsonConverter))]
		public OneOrMany<ExtendedThing> AffectedSite { set; get; }
		[DataMember(Name = "projectAddress", Order = 210)]
		[JsonConverter(typeof(ValuesJsonConverter))]
		public OneOrMany<ExtendedAddress> ProjectAddress { set; get; }
}

I want these Projects to be assigned to a ReceiveAction as the Object property; but since that doesn't deserialize except as a Thing, I've been serializing and assigning the string to the ReceiveActions' Object's AlternateName. After transport I do this: inputObject.Object = JsonConvert.DeserializeObject<Project>(inputObject.Object.First().AlternateName.First().ToString());. That worked originally, but doing some regression testing I now see that a single AffectedSite deserializes as an ExtendedThing, and an AffectedSite array deserializes as null. The AddressCounty, meanwhile, deserializes properly whether it's a single value or an array. In other words, the following string

"{\"@context\":\"http://some.site.io\",\"@type\":\"Project\",\"affectedSite\":[{\"@type\":\"ExtendedThing\",\"@id\":\"http://some.site.io/Site/1\",\"name\":\"Example Site 1\"},{\"@type\":\"ExtendedThing\",\"@id\":\"http://some.site.io/Site/2\",\"name\":\"Example Site 2\"}],\"projectAddress\":{\"@type\":\"ExtendedAddress\",\"addressCounty\":[{\"@type\":\"AdministrativeArea\",\"name\":\"County 1\",\"alternateName\":\"1\"},{\"@type\":\"AdministrativeArea\",\"name\":\"County 2\",\"alternateName\":\"2\"}]}}"

should deserialize like

Project {
  AffectedSite [Site 1, Site 2],
  ProjectAddress { AddressCounty [County 1, County 2] }
}

but instead deserializes like

Project {
  ProjectAddress { AddressCounty [County 1, County 2] }
}

How to set value for AcceptedPaymentMethod on Offer?

On an Offer-object I'm trying to set a value on AcceptedPaymentMethod using the enum PaymentMethod but can't figure out how that's possible to do since that enum is empty? Any suggestion about how to do this?

ValuesJsonConverter doesn't pass JsonSerializer through to ToObject

The ToObject calls on JObject or JToken etc inside the ValuesJsonConverter don't pass the current serializer. This is a problem as custom converters on the serializer are never passed through (eg. StringEnumConverter) to the inner deserialization of the token/object.

This would affect all nested properties that have IThing (or anything derived from it) as a potential value.

The fix is basically just passing the instance of JsonSerializer through to the ToObject method calls within ValuesJsonConverter.

I would add a specific way to reproduce this however I came into this issue from a different/complicated angle. I was trying to deserialize a BreadcrumbList where the list item's "item" field wouldn't deserialize because it was an IThing and there was no defined type. When I tried to use my own converter (basically taking the IThing the serialization process saw and making it instantiate Thing), I saw my converter was never passed down the line into the nested properties.

I'm not sure if it is worth fixing for JSON.Net or just something to keep in mind for #100 .

Issue with HowTo schema

I'm trying to build a HowTo schema like this:

var howToSchema = new HowTo()
{
    Name = "some name",
    Description = "some desc"                            
};

var step1 = new HowToStep()
{
    Url = new Uri("http://example.com#step1"),
    Name = "Name for step1",
    Text  = "Desc for step1",
    Position = 1
};

var step2 = new HowToStep()
{
    Url = new Uri("http://example.com#step2"),
    Name = "Name for step2",
    Text  = "Desc for step2",
    Position = 2
};

//Here is the issue
//howToSchema.Step property is of type Values<ICreativeWork, IHowToSection, IHowToStep, string>
//I cannot add more than one step, which is the main purpose of the how to element
howToSchema.Step = step1;
howToSchema.Step = step2;

The issue is that I cannot add more than one step.

For reference, google has some examples and the howTo schema has a 'step' array. Here is the link: https://developers.google.com/search/docs/data-types/how-to#standard

URL for jsonld from schema.org changed?

I just downloded the source code for Schema.NET with the purpose of trying to see if I can find a way to solve this issue #42, if possible. However running the project Schema.NET.Tool results in the application crashing since calling https://schema.org/version/latest/all-layers.jsonld results in status code 404 Not Found.

Looking at https://schema.org/docs/developers.html it seems like this url has changed, probably to https://schema.org/version/latest/schemaorg-current-https.jsonld?

I tried changing to this url and that way I get information from schema.org but that then results in the following exception:

System.Exception: Check that a new primitive type has not been added.
at Schema.NET.Tool.Services.SchemaService.SetParentAndChildren(List`1 classes) in C:\Source\Schema.NET\Tools\Schema.NET.Tool\Services\SchemaService.cs:line 180
at Schema.NET.Tool.Services.SchemaService.GetObjectsAsync() in C:\Source\Schema.NET\Tools\Schema.NET.Tool\Services\SchemaService.cs:line 53
at Schema.NET.Tool.Program.ExecuteAsync() in C:\Source\Schema.NET\Tools\Schema.NET.Tool\Program.cs:line 65
at Schema.NET.Tool.Program.Main() in C:\Source\Schema.NET\Tools\Schema.NET.Tool\Program.cs:line 45

Any input here would be appreciated.
Best regards
Martin

MissingMethodException on constructors

I was noticing a lot of MissingMethodExceptions in my debug console, and noticed I'm getting it on deserializing my objects from an Azure CosmosDB query response. Looks to be happening a lot, which I'm sure is affecting performance. (Running with latest VS 2019)

Appears to be happening in here:
Schema.NET.dll!Schema.NET.ValuesJsonConverter.ReadJson(Newtonsoft.Json.JsonReader reader, System.Type objectType, object existingValue, Newtonsoft.Json.JsonSerializer serializer)

Exception:
Constructor on type 'Schema.NET.OneOrMany1[[System.Nullable1[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]' not found

mscorlib.dll!System.RuntimeType.CreateInstanceImpl(System.Reflection.BindingFlags bindingAttr, System.Reflection.Binder binder, object[] args, System.Globalization.CultureInfo culture, object[] activationAttributes, ref System.Threading.StackCrawlMark stackMark) Line 5229
at f:\dd\ndp\clr\src\BCL\system\rttype.cs(5229)

Looks to be happening here:

        object value = converter.ReadJson(reader, objectType, existingValue, GetInternalSerializer());

objectType:

{Name = "Nullable1" FullName = "System.Nullable1[[Schema.NET.Values2[[System.Nullable1[[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]], Schema.NET, Version=4.2.0.0, Culture=neutral, PublicKeyToken=fc5550082a9c642c]]"}

reader.path:
thing.model.position

full JSON (the 'thing' part is a Schema.NET MusicRecording):

{{
"thing": {
"model": {
"@context": "http://schema.org",
"@type": "MusicRecording",
"name": "There, There",
"identifier": "77SPrxY5gn6VPrKPGrfLnM",
"url": "https://open.spotify.com/track/77SPrxY5gn6VPrKPGrfLnM",
"isFamilyFriendly": true,
"position": "1.9",
"byArtist": {
"@context": "http://schema.org",
"@type": "MusicGroup",
"name": "Radiohead",
"identifier": "4Z8W4fKeB5YxbusRsdQVPb"
},
"duration": "PT5M23.6S"
}
},
"ownerType": {
"value": 0,
"name": "Vendor"
},
"thingType": {
"value": 2,
"name": "MusicRecording"
},
"application": {
"id": "73693d68-7b1e-45d2-8294-a5983fe2ae2b"
},
"sources": {
"Spotify": {
"feedReaderSession": "45f856e6-34ce-49ed-9a7f-f5db10e131c0",
"feedType": {
"value": 0,
"name": "Vendor"
},
"feedReaderType": {
"value": 1,
"name": "HttpProcessor"
},
"feedReaderIdentifier": "77SPrxY5gn6VPrKPGrfLnM"
}
},
"sourceIdentifiers": [
"77SPrxY5gn6VPrKPGrfLnM"
],
"feedReaderConnectorType": {
"value": 8,
"name": "Spotify"
},
"feedReaderType": {
"value": 1,
"name": "HttpProcessor"
},
"feedReaderIdentifier": "77SPrxY5gn6VPrKPGrfLnM",
"name": "There, There",
"id": "8f534e34-0f76-4302-8fc4-87d23b0da9e8",
"state": "Created",
"hash": 1857201296850043839,
"creationDate": {
"date": "2019-06-16T06:50:18Z",
"epoch": 1560667818
},
"type": "Track",
"parent": {
"id": "03eaa02f-666b-4963-9cb1-f366cfb25507"
}
}}

Properties assigned `null` are rendered by ToString()

Even though the JsonSerializerSettings specify NullValueHandling = NullValueHandling.Ignore if you assign a null to a property it'll start coming out in the serialized response.

I believe this is because the property is no longer null, but a Values<T> wrapping the null, which has HasValue = false.

Added a unit test to check this locally, on master, but then realised it's not an issue in master, so I'm guessing there's some unreleased changes in master, perhaps part of the PR around multiple types in properties?

As far as I can see not possible to mix types in Values{T1,....Tn}

I am trying to make a parser from html microdata to Schema.Net. As far as I can see now, I can only use 1 type in Values with more then 1 generic argument.

e.g. I would like to be able to parse an image using url, but somewhere later in the document I would like to add ImageObject type, because the creator of the html page made a differnce in types of images.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.