I am unable to deserialize the Tags property of my JSON:
{
"posts": [
{
"ID": 7096,
"title": "Backwards Pipe Operator",
"URL": "https://bizmonger.wordpress.com/2017/10/26/backwards-pipe-operator/",
"tags": {
"F#": {
"ID": 6012,
"name": "F#"
}
}
}
]
}
From the JSON above I provided the following types:
type Post = {
title: string
URL: string
Tags: JToken seq // Used to refer to the string instead of the property type
}
type Response = { posts: Post list }
I'm running into an exception when attempting to deserialize the Tags property of a Post value:
let settings = JsonSerializerSettings()
settings.MissingMemberHandling <- MissingMemberHandling.Ignore
let result = JsonConvert.DeserializeObject<Response>(json, settings)
Newtonsoft.Json.JsonSerializationException occurred
HResult=0x80131500 Message=Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.IEnumerable`1[Newtonsoft.Json.Linq.JToken]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly. To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object. Path 'posts[0].tags.F#', line 1, position 1582. Source=
StackTrace: at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObject(JsonReader reader, Type objectType, JsonContract contract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerMember, Object existingValue) ...
Appendix:
Here's the JSON URL
try let url = String.Format(ArticlesUrl, user.AccessId)
let response = client.GetAsync(url) |> Async.AwaitTask
|> Async.RunSynchronously
if response.IsSuccessStatusCode
then let json = response.Content.ReadAsStringAsync() |> Async.AwaitTask
|> Async.RunSynchronously
let settings = JsonSerializerSettings()
settings.MissingMemberHandling <- MissingMemberHandling.Ignore
let result = JsonConvert.DeserializeObject<Response>(json, settings);
The library tells you very explicitly what's wrong: Cannot deserialize ... JSON object ... into type 'JToken seq' because the type requires a JSON array to deserialize correctly
.
Seq
is a sequence (i.e. a list, an array, an enumeration) of stuff. It corresponds to JSON array, not to JSON object.
To deserialize a JSON object without knowing property names in advance, use IDictionary
:
type Post = {
title: string
URL: string
Tags: IDictionary<string, JToken>
}
Further, if you do know the shape of each individual tag (ID
+ name
), then you can do even better:
type Tag = { ID: string; name: string }
type Post = {
title: string
URL: string
Tags: IDictionary<string, Tag>
}
User contributions licensed under CC BY-SA 3.0