Grayden Hormes Grayden Hormes - 1 month ago 13
JSON Question

Json.net JObject.Parse erroring on complex json

The following code:

let resp = string(argv.GetValue 0)

let json =JObject.Parse resp


gives this error:

An unhandled exception of type 'Newtonsoft.Json.JsonReaderException'
occurred in Newtonsoft.Json.dll

Input string '2.2.6' is not a valid number.
Path 'items[0].versionName', line 1, position 39.


where argv is this input:

{
"totalCount":1,
"items":[
{
"versionName":"2.2.6",
"phase":"PLANNING",
"distribution":"EXTERNAL",
"source":"CUSTOM",
"_meta":{
"allow":[
"GET",
"PUT",
"DELETE"
],
"href":"url",
"links":[
{
"rel":"versionReport",
"href":"url"
},
{
"rel":"project",
"href":"url"
},
{
"rel":"policy-status",
"href":"url"
}
]
}
}
]
}


How can I fix this? Is there a simple way to implement a json reader that does not error here?

I also get this error:

An unhandled exception of type 'Newtonsoft.Json.JsonReaderException'
occurred in Newtonsoft.Json.dll

Error parsing undefined value. Path 'items[0].name', line 1, position 28.


With this input:

{
"totalCount":1,
"items":[
{
"name":"uaa",
"projectLevelAdjustments":true,
"source":"CUSTOM",
"_meta":{
"allow":[
"GET",
"PUT",
"DELETE"
],
"href":"url",
"links":[
{
"rel":"versions",
"href":"url"
},
{
"rel":"canonicalVersion",
"href":"url"
}
]
}
}
]
}


I am trying to read in json of many different schemas that I did not make or know. The first error seems to be because it is trying to generate a float from something that should be output as a string. The second sounds like the schema is too complex and a type would be needed to properly parse it using Json.Deserialize but I'm not sure how to do that and it would take too much time as there are too many schemas to make a types for them all. Is there any way around both these things?

EDIT for Ringil

open Newtonsoft.Json
open Newtonsoft.Json.Linq
open FSharp.Interop.Dynamic

[<EntryPoint>]
let main argv =
let resp = string(argv.GetValue 0)

//let json = JObject.Parse resp

let json = JsonConvert.DeserializeObject(resp)


Doesn't work, same error. I'm not sure what you're suggesting. I read that answer and couldn't figure out where they wanted me top put ? marks

let json = JsonConvert?DeserializeObject(resp)


does not comppile so I'm confused as to FSharp.Interop.Dynamic helps. You will have to spell it out, it's not clear.

EDIT 2: Ringil and Foggy Finder say they are not getting exceptions, but I am on two different computers :/

This is the input I am giving to argv, I am doing it through the debug in the properties dialog for the solution, the urls are again removed:

{"totalCount":1,"items":[{"versionName":"2.2.6","phase":"PLANNING","distribution":"EXTERNAL","source":"CUSTOM","_meta":{"allow":["GET","PUT","DELETE"],"href":"https://url","links":[{"rel":"versionReport","href":"https://url"},{"rel":"project","href":"https://url"},{"rel":"policy-status","href":"https://url"}]}}]}


it is the same as the first input above but compacted to one line. If I make 2.2.6 into a normal number like 226 to try satisfy it I get the same as the second exception expect at pos 41 which is the begginning of the string "226". Perhaps something else is going wrong here if no one else is getting exceptions?

Answer

In C# you can use dynamic with something like this:

var json = JsonConvert.DeserializeObject(resp)

And then you could access properties with something like: json.totalCount.

In F# land, this question gives some suggestions for how you might deal with dynamic objects. If you use the package FSharp.Interop.Dynamic you can get the value of totalCount in your example with something like this:

let value:obj = json?totalCount?Value

which gives 1L on my computer.

Comments