C# JSON Parse gives error 'System.ArgumentNullException' when parsing JSON array - c#

I'm trying to parse this JSON:
{"error":[],"result":{"XETHXXBT":{"a":["0.023769","64","64.000"],"b":["0.023756","42","42.000"],"c":["0.023756","1.21518360"],"v":["74038.22109284","130984.00945101"],"p":["0.023689","0.006974"],"t":[1272,2332],"l":["0.023440","0.023440"],"h":["0.024091","0.024669"],"o":"0.024084"}}}
The piece of data I want to get is
"c":["0.023756","1.21518360"],
More to the point, the first value of "c". The code I am using is:
JObject jObject = JObject.Parse(json);
double balance = (double)jObject["c"];
What am I doing wrong? How can I just get the first value of the "c" array?
Thanks!
Here is the full error report: http://pastebin.com/4S204aUG

To get to c do the following:
var o = JObject.Parse(<yourjsontext>);
var result = o["result"];
var XETHXXBT = result["XETHXXBT"];
var c = XETHXXBT["c"];
var value1 = (double) c[0];
var value2 = (double) c[1];

Your problem is that your object is more complicated than it looks.
The answer is jObject['results']['XETHXXBT']['c'][0] or jObject['results']['XETHXXBT']['c'][1]. Take a look at it with a prettifier.
{
"error":[
],
"result":{
"XETHXXBT":{
"a":[
"0.023769",
"64",
"64.000"
],
"b":[
"0.023756",
"42",
"42.000"
],
"c":[
"0.023756",
"1.21518360"
],
"v":[
"74038.22109284",
"130984.00945101"
],
"p":[
"0.023689",
"0.006974"
],
"t":[
1272,
2332
],
"l":[
"0.023440",
"0.023440"
],
"h":[
"0.024091",
"0.024669"
],
"o":"0.024084"
}
}
}
As you can see, your base object does not have a c property, so naturally it is throwing an error when you attempt to access (and automatically type cast) that nonexistent property.

Use Like that it will give you more flexibility to get the data , if you don't know how may level depth you have to search it will become very difficult and code will be look like tightly coupled or hardcoded whenever you working with json or xml follow class structure it will help to debug or understand the structure as well
public class Test {
public string[] error { get; set; }
public string result { get; set; }
}
public class Result {
public List<Values> XETHXXBT { get; set; }
}
public class Values {
public List<Double> a { get; set; }
public List<Double> b { get; set; }
public List<Double> c { get; set; }
}
After that class Jsonconvert.deserializeObject<Test>(jsonString); and store it in object you will proper json data in object and after that you can traaverse and get desired data according to your need.Hope it will help you T
Thanks

Related

How to pass JSON string as array

[
{"id": 1, "name": "danny_devito", "img": "/images/1"},
{"id": 2, "name": "jim_carey", "img": "/images/2"},
{"id": 3, "name": "tyler_1", "img": "/images/3"}
]
[System.Serializable]
public class Players {
public int id;
public string name;
public string img;
}
[System.Serializable]
public class PlayersArray {
public Players[] playersData;
}
string playersJson = File.ReadAllText(Application.dataPath + "/playersFile.json");
PlayersArray loadedPlayerData = (PlayersArray)JsonUtility.FromJson<PlayersArray>(playersJson);
Debug.Log("Danny Boy: " + loadedPlayerData.playersData[0].name);
I followed tons of tutorials and none of it works!
It gives me this error:
You're trying to deserialize an object. But the JSON you show isn't an object. It's an array. Deserialize it into a collection:
var loadedPlayerData = JsonUtility.FromJson<List<Players>>(playersJson);
Or even just an array:
var loadedPlayerData = JsonUtility.FromJson<Players[]>(playersJson);
As an aside... Names are important. Players is a misleading name for a player. The class should be called Player instead.
Additionally, this class might not deserialize at all, depending on how the JSON serializer works. They tend to use properties, not fields. You'll likely want to use properties anyway:
public class Players {
public int id { get; set; }
public string name { get; set; }
public string img { get; set; }
}
For further improvements, you will probably also want to capitalize the property names. The JSON serializer might be case-sensitive (I don't think they tend to be by default, but it's worth testing) and you may need to add attributes to the properties to specify their names in the JSON. But just to get the code working, at the very least you'll most likely need properties here instead of fields.

How can I deserialize JSON when the object type is not known beforehand?

So I have an API and front-end that I am developing, and I need a way to deserialize JSON when one of the values could be a List of multiple different types. Currently I'm deserializing it into a List<dynamic> but that's a huge pain to work with in my context.
public class WorkbenchAPI
{
public string status { get; set; }
public HttpStatusCode code { get; set; }
public string error { get; set; }
public string guid { get; set; }
public List<dynamic> results { get; set; }
}
Sample JSON
{
"status": "ok",
"code": 200,
"error": null,
"guid": "1234",
"results": [
{
"SamAccountName": "dizbuster",
"CN": "Buster, Diz",
"EmailAddress": "dizbuster#whatever.com",
}
]
}
In the above example JSON, results should be deserialized into type List<ClassA> for example.
{
"status": "ok",
"code": 200,
"error": null,
"guid": "1234",
"results": [
{
"data": "127.0.0.1",
"owner": "dizbuster",
"email": "dizbuster#whatever.com",
},
{
"data": "192.168.0.1",
"owner": "dizbuster",
"email": "dizbuster#whatever.com",
}
]
}
Where as in this sample, results should be deserialized into List<ClassB>.
Some of the field names may show up in different types, but some are not. Functionally they are two different types representing the outputs from two separate API calls, so I'd like to have it deserialize into specific object types as opposed to using dynamic or a monolithic object that contains every possible field.
Currently I'm taking the List<dynamic> and serializing it back into a temporary JSON string, then deserializing it again into the List<ClassA> or whatever. This seems like a bad way to do it, and is cumbersome to work with.
Is there a better way to structure this or to handle the serialization/deserialization? I have full control over both ends so it's not too difficult for me to alter the JSON as well if needed. Also, I know that a particular API call will return JSON that looks like this, while another API call will return JSON that looks like that. Each case should result in a differently typed list
Since you know in advance what type of data is being returned in "results" for each API call, you can make your WorkbenchAPI class generic:
public abstract class WorkbenchAPI
{
protected abstract IReadOnlyCollection<dynamic> GetResults();
public string status { get; set; }
public HttpStatusCode code { get; set; }
public string error { get; set; }
public string guid { get; set; }
public IReadOnlyCollection<dynamic> results => GetResults();
}
public class WorkbenchAPI<T> : WorkbenchAPI where T : class
{
protected override IReadOnlyCollection<dynamic> GetResults() => results;
public new List<T> results { get; set; } = new List<T>();
}
Notes:
I extracted the common properties into an abstract base class to allow them to be accessed by pre-existing non-generic code that does not care about the specific type of result.
I also added a IReadOnlyCollection<dynamic> results to the base class to ease integration with pre-existing code, e.g.:
// Deserialize to the concrete, known type
var root = JsonConvert.DeserializeObject<WorkbenchAPI<ClassA>>(json);
// Access the results in a type-safe manner:
var accounts = root.results.Select(r => r.SamAccountName).ToList();
// Upcast to the base class in code where we don't need to know about the specific result type.
// E.g.: accessing root properties like guid or getting the result count.
WorkbenchAPI baseRoot = root;
var count = baseRoot.results.Count;
var guid = baseRoot.guid;
However, adding access to the results as a non-generic read-only collection of dynamic objects is optional, and could be removed if your legacy code can be rewritten to be generic.
Demo fiddle here: https://dotnetfiddle.net/lbTs1z

Deserializing JSON issue

I need to deserialize just part of a JSON string returned from a server. The 'myData' portion in the JSON string below.
My JSON string is structured as follows.
{
"data": {
"CODE": {
"someData": {
"h": "foo",
"id": "City",
"lat": "11.11111"
},
"feedMe": [
[
{
"myData": {
"item1": "a",
"item2": "b",
"item3": "c"
},
"moreData": {}
}
]
]
}
}
}
In Unity there is the JSONutility.FromJson method
https://docs.unity3d.com/ScriptReference/JsonUtility.FromJson.html
but unsure how I would either
1 pass only the 'myData' portion to this method.
or
2 Deserialize the entire string
An alternativ to using JsonUtility there is good old SimpleJSON which allows you to only access a certain field of your json like e.g.
var N = JSON.Parse(the_JSON_string);
var myData = N["data"]["CODE"]["feedMe"][0][0];
var item2 = myData["item2"].Value;
In general the simplest way to get the needed c# class structure for your json is always using json2csharp and make all classes [Serializable] and remove the {get; set;} in order to use fields instead of properties. Something like this
[Serializable]
public class SomeData
{
public string h;
public string id;
public string lat;
}
[Serializable]
public class CODE
{
public SomeData someData;
public List<List<MyData>> feedMe;
}
[Serializable]
public class MyData
{
public string item1;
public string item2;
public string item3;
}
[Serializable]
public class Data
{
public CODE CODE;
}
[Serializable]
public class RootObject
{
public Data data;
}
Instead of List<T> you can also use T[] if you like. And the class names actually don't matter but the structure and field names have to match.
and then use
var root = JsonUtility.FromJson<RootObject>(THE_JSON_STRING);
var myData = root.data.CODE.feedMe[0][0];
var item2 = myData.item2;
As already comented however there is a nested array in your array .. not sure if this is intended.
well, use one of the powerful json nuget -newtonsoft.json , then in your code you can iterate the values like below
var files = JObject.Parse(YourJSON);
var recList = files.SelectTokens("$..data").ToList();
foreach (JObject obj in recList.Children())
{
foreach (JProperty prop in obj.Children())
{
var key = prop.Name.ToString();
var value = prop.Value.ToString();
//Do your stuffs here
}
}
JsonUtility not work whit json files, this only for save and load basic public variables of some class. Asset Store have many frameworks for parse json. p.s. your json is strange, [] its array and you have feedMe:[[{myData, moreData}]]. One array whene just one object in array... parse confusing.

Deserialize JSON string in to multiple C# objects

I have a JSON string in below format for which I want to deserialize it into C# List. But the record number "1","2","3" (it can be upto 1,2,3...n depends on the json response each time) in JSON restricting me to deserialize it into C# object using Newtonsoft.Json
{
"1":{
"UID":"1",
"LICENCENO":"licenseno",
"NAME":"ABC"
},
"2":{
"UID":"2",
"LICENCENO":"licenseno",
"NAME":"PQR"
},
"3":{
"UID":"3",
"LICENCENO":"licenseno",
"NAME":"XYZ"
}
}
I am using below code for deserialization
var result = Newtonsoft.Json.JsonConvert.DeserializeObject<List<DriverMaster>>(json);
I have DriverMaster class created as-
public class DriverMaster
{
public string UID { get; set; }
public string LICENCENO { get; set; }
public string NAME { get; set; }
}
Deserialization line giving unhandled exception, I know I am doing it in wrong way, because DriverMaster json object cannot be extracted into c# directly without doing something to record number 1,2,3...n in c#. Can anyone please help me to sort it out? Thanks in advance.
You were close:
var result = JsonConvert.DeserializeObject<Dictionary<string, DriverMaster>>(json)
.Select(x => x.Value)
.ToList();
Solution.
Change your code to use...
var result = JsonConvert.DeserializeObject<Dictionary<int, DriverMaster>>(json);
Explaination
The type is not the same... The List<DriverMaster>type will convert to JSON like so...
{
"1":
{
"DriverMaster": {
"UID":"1",
"LICENCENO":"licenseno",
"NAME":"ABC"
}
}
}
This doesn't match what you showed in your question...
The type that you are looking for is actually Dictionary<int, DriverMaster>, which is a key/value pair which will output a JSON string like so
{
"1": { ... },
"2": { ... },
"3": { ... }
}
In order to fix that, you need to use the Dictionary<int, DriverMaster> type instead.
For these types of things I like to use the often overlooked feature of JToken.SelectTokens. This function allows you to select tokens within a json string and permits the use of wildcards.
Here's some code that will deserialize your sample by selecting past the 1,2,3...N in the json:
public static IEnumerable<DriverMaster> Deserialize(string json)
{
return JToken.Parse(json).SelectTokens("*")
.Select(jToken => jToken.ToObject<DriverMaster>());
}
The * basically says to select all tokens after the root, so it's selecting the values associated with 1, 2, 3.. etc... Here's another SO answer that shows a more complicated usage of the SelectTokens method.
You need to use
public class DriverMaster
{
public string UID { get; set; }
public string LICENCENO { get; set; }
public string NAME { get; set; }
}
public class Root
{
[JsonExtensionData]
public IDictionary<string,JToken> Data {get;set;}
}
and
var result = Newtonsoft.Json.JsonConvert.DeserializeObject<Root>(json);
If you want to have result as List, you can parse the result as.
var list = new List<DriverMaster>();
foreach(KeyValuePair<string, JToken> token in result.Data)
{
list.Add(token.Value.ToObject<DriverMaster>());
}
That would give you the desired result as
1 licenseno ABC
2 licenseno PQR
3 licenseno XYZ

How can I return my object property name as node name

I am stuck while returning api result, I have a class like
public partial class Sample
{
[JsonProperty("classificator")]
public List<Classificator> Classificator { get; set; }
}
public partial class Classificator
{
[JsonProperty("Value")]
public string Value { get; set; }
[JsonProperty("Description")]
public string Description { get; set; }
}
Let's say GetJson method retrieve our data from the database, there are 2 records and the data like
-- Value - Description
1- A - AXA
2- B - BXA
response = GetJson(); // this method gets data from db
return Content(HttpStatusCode.OK, response);
when I return this, it's like
{
"classificator": [{
"Value": "A",
"Description": "AXA"
}, {
"Value": "B",
"Description": "BXA"
}
]
}
but I would like to see like, I want to see bellowing result;
{
"classificator": [{
"A": "AXA"
}, {
"B" : "BXA"
}
]
}
I would like to ask you maybe someone knows a good practice or document(tutorial) about it.
I solve it by using, Dictionary < string, model >
but I need to return a huge nested field I cant implement this solution for all different nodes.
I solved by using Dictionary< string, object >
I put 2 nested objects inside of an object value. In my case it looked some complex I refactor and try to work through readable dictionary hierarchy.
basically for this example it something like below,
Dictionary<string, object> fooDict = new Dictionary<string, object>();
fooDict.Add("A", "AXA"); // in my case I put 2 nested object to value field
fooDict.Add("B", "BXA");
var serializedObject = JsonConvert.SerializeObject(fooDict);
using (System.IO.StreamWriter file = new System.IO.StreamWriter(#"C:\xxx\result.txt", true))
{
file.WriteLine(serializedObject);
}

Categories