Read value from nested Json object - c#

I am trying to read a value from a nested Json object, but I am getting a Parse error:
My Json object:
{
"MessageId": "f6774927-37cf-4608-b985-14a7d86a38f9",
"Time": "2017-04-06T16:28:38.0719933+02:00",
"Data":
{
"ID":
{
"value": "0008044834"
},
"Carrier":
{
"value": 0
},
"Tool":
{
"value": 0
}
}
}
var myJsonString = File.ReadAllText(_currentDictory.FullName + #"\test\" + completeFilename);
var myJObject = JObject.Parse(myJsonString);
var serial = myJObject.SelectToken("Data.ID").Value<String>();
System.InvalidCastException
HResult=0x80004002
Message=Cannot cast Newtonsoft.Json.Linq.JObject to Newtonsoft.Json.Linq.JToken.
Source=Newtonsoft.Json
Reading other values such as "MessageID" works withou any problems, but as soon as I try to get "Data.XYZ" I am getting the error above.

You need to add value to your json path:
var serial = myJObject.SelectToken("Data.ID.value").Value<String>();
Your current path selects JObject containing one property named value and you can't convert it directly to string.

MessageId is a string. So you can directly read its value.
Data on the other hand contains objects (see the { and } ). Therefor you need to use
var serial = myJObject.SelectToken("Data.ID.value").Value<String>();
Also see:
Getting 'Cannot cast Newtonsoft.Json.Linq.JObject to Newtonsoft.Json.Linq.JToken' when retrieving items from JSON

Related

Newtonsoft.Json: Error reading JObject from JsonReader. Current JsonReader item is not an object: StartArray

Hi I am passing the below string in my code in line var json = JObject.Parse(jStr); and I get the error as
System.Private.CoreLib: Exception while executing function: Function1.
Newtonsoft.Json: Error reading JObject from JsonReader. Current
JsonReader item is not an object: StartArray.
Can someone please explain me how should I fix this. Is it because it is an array kind? At the end my passed string will be an array. how can I fix this?. here is the sample string(one object from the array) which I am passing in above line
[
{
"_id": "_AUQ9",
"im:SiceErrors": {
"errors": [
{
"_id": "O9UQ9_0",
"ErrorMessage": "Uype",
"Parameter": "r:type",
"ParameterValue": "[\n \"~:bbl:P924\",\n \"~:corer:ag\"\n]",
"RefObjectParameter": "type_key",
"Project": "NPOS+1"
}
]
},
"cullad-tag:Cject": "P|GT",
"bbl:P1014": "PIGT",
"cullad-tag:MoomosBaseObjectDescription": "Gate Valve",
"bbl:P3935": "Gve",
"cullad-tag:CreateDate": "15.10.2021",
"cullad-tag:MoomosDescription": "P2",
"cullad-tag:MoomosUID": "A49",
"bbl:011772": "UQ9",
"cullad-tag:Description": "P2",
"cullad-tag:Discipline": "U",
"bbl:P101001445": "bbl:P163",
"cullad-tag:FLabel": "FFeed",
"bbl:P1094": "pd:P1299",
"bbl:P10791": "V",
"cullad-tag:FutureTag": "No",
"cullad-tag:IndexType": "MV",
"bbl:P138": "bbl:P1563",
"cullad-tag:IsTopTag": "No",
"bbl:P7": "No",
"cullad-tag:MountedOn": "F-18UD800",
"bbl:P4024": "F-18800",
"bbl:P1834": "pd:P1094",
"bbl:P1803": "8120",
"cullad-tag:SubProjectCategory": "Feed",
"cullad-tag:SubProjectName": "SUB",
"cullad-tag:System": "18",
"bbl:P01660": "bbl:P15326",
"cullad-tag:TagNumber": "F-120",
"bbl:P10022": "F-20",
"cdf:type": [
"bbl:P10924",
"bbl:P101907",
"bbl:P101003632",
"bbl:P13932",
"bbl:P21",
"iso15926:InanimatePject",
"iso15926:Object",
"Moomos:PopoFeedTag"
],
"primarycdf:type": "bbl:P924"
}
]
Your example is a single object inside an array.
#SeeSharp propose to wrap that array.
The opposite way is, if that's always the case, that you can just parse the object inside that array (removing first and last character):
var json = JObject.Parse(jStr.Remove(str.Length - 1).Remove(0, 1));
Otherwise, I guess you just adapt your code to handle an array, and not an object (which looks the better way to do so)
EDIT :
Since there is multiple object inside your JArray, just iterate over it :
foreach (JObject item in JArray.Parse(jStr))
{
DoStuffOnJObject(item) // call your method
}
You have to wrap your string to make a valid json object:
var json = JObject.Parse("{ \"Data\":" + jStr + "}");
The resulting object will contain property Data with data from json
edited by comments: OR try this approach:
foreach(JObject obj in JArray.Parse(jStr))
{
// todo: pass an object to a method that requires an JObject to process
}

Dynamic object in c#

I'm trying to define a data structure using JSON and validate the actual data using structure definition with JSON definition. I'm trying this in c#.
for example:
"PlayerScore":{
"fields":[
{
"name":"Runs",
"type":"short",
"isRequired":true
},
{
"name":"Wickets",
"type":"byte",
"isRequired":false
}
]
Above is the definition of the data structure. Below is the actual data.
{
"Runs": 20,
"Wickets": 1
},
{
"Runs": 20
}
I want to validate the data type of "Runs" and "Wickets" only if it is a required field.
Newtonsoft's Json.NET (https://www.nuget.org/packages/Newtonsoft.Json/) supports JSON validation versus its schema. Here is the example from their documentation.
Sample where validation returns true
string schemaJson = #"{
'description': 'A person',
'type': 'object',
'properties':
{
'name': {'type':'string'},
'hobbies': {
'type': 'array',
'items': {'type':'string'}
}
}
}";
JsonSchema schema = JsonSchema.Parse(schemaJson);
JObject person = JObject.Parse(#"{
'name': 'James',
'hobbies': ['.NET', 'Blogging', 'Reading', 'Xbox', 'LOLCATS']
}");
bool valid = person.IsValid(schema);
// true
Sample where validation returns false
JsonSchema schema = JsonSchema.Parse(schemaJson);
JObject person = JObject.Parse(#"{
'name': null,
'hobbies': ['Invalid content', 0.123456789]
}");
IList<string> messages;
bool valid = person.IsValid(schema, out messages);
// false
// Invalid type. Expected String but got Null. Line 2, position 21.
// Invalid type. Expected String but got Float. Line 3, position 51.
https://www.newtonsoft.com/json/help/html/JsonSchema.htm
Didn't quite get you but if you are trying to validate a json against a Json Schema. This post might be what u need. Json Schema Validation
Not sure why u wanna go that route though. Would it suffice for you to make a C# model and validate the json against it using data annodations? (assuming its an api) Learn about them here Data Annotations

error deserialization dynamic json

I have the following Json , which has a dynamic set of values
[ {
"Type": "Animal" }, {
"Profession": "Dog" } ]
I want to read it into an object
List<List<KeyValuePair<String,String>>>
this works :
var objectList = JsonConvert.DeserializeObject<List<dynamic>>(rawStringJsonData);
but when I try
var objectList = JsonConvert.DeserializeObject<List<List<KeyValuePair<String,String>>>(rawStringJsonData);
I get an error
Additional information: Cannot deserialize the current JSON object
(e.g. {"name":"value"}) into type
You can read it as a List<Dictionary<string,string>> and then cast it to
List<List<KeyValuePair<String,String>>>
Try this:
var rawStringJsonData = "[ { \"Type\": \"Animal\" }, { \"Profession\": \"Dog\" } ]";
var dictList = JsonConvert.DeserializeObject<List<Dictionary<string,string>>>(rawStringJsonData);
List<List<KeyValuePair<string,string>>> objectList =
dictList.Select(i => i.ToList()).ToList();
If you use the debugger to inspect the type of your first try, its just deserializing to a list of JTokens, and seeing as that you want a list of key value pairs I'd say that not really anything useful.
The List<List<KeyValuePair<String,String>>> datatype does not match your data. That would maybe look something like this
[ {"Key": "Type", "Value": "Animal" }, {"Key": "Profession", "Value": "Dog" } ]
In this case I'd probably deserialize to a dictionary instead:
var objectList = JsonConvert.DeserializeObject<List<Dictionary<string,string>>>(rawStringJsonData);

C# - parse JSON with dynamic and access property name with colon

When getting a JSON with property with :
i.e.
{
"root": {
"sim:names": [{
"name": "Tom"
},
{
"name": "David"
}]
}
}
I'm using Newtonsoft Dynamic parse.
var data = JsonConvert.DeserializeObject<dynamic>(jsonString);
I'm trying to access
data.root.sim:names
But getting compilation error "Invalid expression term ':'"
How can I access it?
You should convert it to object
var data = JsonConvert.DeserializeObject<Object>(jsonString);
And access it like this:
var value = ((JObject)data)["root"]["sim:names"];

Capture json data from Steam API

So I what I am trying to do is capture/extract specific data from Steams API for dota2 heroes. I am using C# to do this with this method.
https://api.steampowered.com/IEconDOTA2_570/GetHeroes/v0001/?key=2D13D618DA712015812E970165632F02&language=en_us
{
"result": {
"heroes": [
{
"name": "npc_dota_hero_antimage",
"id": 1,
"localized_name": "Anti-Mage"
},
]
}
This is the code I have been trying with:
WebClient c = new WebClient();
var data = c.DownloadString("https://api.steampowered.com/IEconDOTA2_570/GetHeroes/v0001/?key=2D13D618DA712015812E970165632F02&language=en_us");
JObject o = JObject.Parse(data);
string heroname = (string)o["name"];
But it only returns an error saying the value of "heroname" is null.
Any ideas?
o is going to be an object that contains one key: result. o["result"] will in turn contain a key called heroes. o["result"]["heroes"] is an array of objects. So o["result"]["heroes"][0] will be the first item, and o["result"]["heroes"][0]["name"] is the name from the first item.

Categories

Resources