Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Type] annotation for properties #9

Open
tpluscode opened this issue Jan 13, 2017 · 9 comments · May be fixed by #8
Open

[Type] annotation for properties #9

tpluscode opened this issue Jan 13, 2017 · 9 comments · May be fixed by #8

Comments

@tpluscode
Copy link
Contributor

tpluscode commented Jan 13, 2017

The TypeAttribute proposed by @asbjornu (see #6) could also be used with properties to declare literal type:

[Type("xsd:date")]
public DateTime BirthDate { get; set; }

would serialize as smth like

"birthDate": {
  "@value": "2016-10-10",
  "@type": "xsd:date"
}
@tpluscode
Copy link
Contributor Author

At this point I'm kind of unsure whether or how the [Type] annotation would affect serialization. In the example above a DateTime would by default serialize as a ISO date time typed as xsd:dateTime (when #8 is merged).

So would there have to be a (extensible?) way to ensure that only the date portion of a DateTime is serialized. Similar mechanism could be used in other scenarios:

  1. xsd:time
  2. xsd:gYear etc.
  3. xsd:nonNegativeInteger and other numeric types that don't have a direct C# counterpart
  4. custom types such as date/time from NodaTime

@tpluscode
Copy link
Contributor Author

Ok, so regarding the previous comment, I now see that this will be possible by using a custom JsonLdLiteralConverter and overriding the WriteJsonLdValue method as necessary.

@tpluscode
Copy link
Contributor Author

Also, CreateProperty is the right place to read the [Type] attribute and apply it to the converter

@tpluscode tpluscode linked a pull request Jan 14, 2017 that will close this issue
@asbjornu
Copy link

How would a custom JsonLdLiteralConverter be registered? The neatest would be if one class could be registered per literal type, so you don't end up with one gigantic CustomJsonLdLiteralConverter. That's one part of JSON.NET I don't particularly like the design of and that I always find to become very messy once I start plugging in custom code, so if an elegant way to extend this was conjured, that would be awesome.

@tpluscode
Copy link
Contributor Author

Definitely, one converter for a literal type. I'm not sure what in the design of json.net you don't like. There are three options for setting converters

  1. By annotating property
    [JsonConverter(IpAddressConverter)]
    public IPAddress IP { get; set; }
  2. By annotating class
    [JsonConverter(IpAddressConverter)]
    public class IPAddress { }
  3. By adding directly to JsonSerializer
    JsonSerializer serializer;
    serializer.Convertes.Add(new IpAddressConverter());

Don't they work for you?

@tpluscode
Copy link
Contributor Author

Ah, and for the third to work, the converter must override bool CanConvert(Type objectType)

@asbjornu
Copy link

When a the type is serialised to a string, you have no idea whether you actually can deserialise it. We don't have enough contextual information in the CanConvert() method to know whether we can or cannot convert the value from a string. And when a converter has said that it can convert a value, it has no way to start parsing and then give up half way through, as far as I know.

If the CanConvert() method was provided with the whole JToken, we could have inspected it, associated its name with the JSON-LD term and then see whether that matched, but since we only have access to the System.Type and JSON.NET don't know about JSON-LD for type annotations, the deserialisation becomes hard or perhaps even impossible to get right.

Perhaps I've been digging at this from the wrong angle, but that's at least the problems I've had related to this previously.

@tpluscode
Copy link
Contributor Author

OIC. Like you said, one converter for one (literal) type. Instead of using string you could wrap it in a specialized type and have a dedicated converter. Otherwise I don't see how you would use multiple converter types for multiple fields which are all strings.

@asbjornu
Copy link

Exactly. You would have to set TypeNameHandling to Objects, which pollutes the JSON with a $type (IIRC) property alongside every value. If we could adjust that to be @type, it wouldn't be too bad, but afaik, we can't.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants