Parse a JSON string - c#

I have a JSON string like following string
{
FlightId : 1,
[
{
AirplaneId : 1
},
{
AirplaneId : 2
}
]
}
I have defined 2 classes to convert this JSON string to the objects of these 2 classes :
class Airplane
{
int AirplaneId;
}
class Flight
{
int FlightId;
List<Airplane> Airplanes;
}
During convert the string to these classes objects I get an error. The error tells me that JSON string is not recognized and I should define a name for the list in my JSON string. I can not change the JSON string , how to define my class to convert this JSON String

Yes, you get an error since that is not a valid JSON.
In order to make it valid, you need to have a key to match your list value:
{
"FlightId" : 1,
"Airplanes": [
{
"AirplaneId" : 1
},
{
"AirplaneId" : 2
}
]
}
Also, you need to wrap your key values in quotes.
You can use https://www.jsoneditoronline.org/ in the future to make sure your JSON strings are valid.

The problem is your array, you need to define a key for it, like:
{
"FlightId" : 1,
"Airplanes": [
{
"AirplaneId" : 1
},
{
"AirplaneId" : 2
}
]
}
Airplanes must be a list in your class later.
JSON is a "Key-Value" based format, so every value (even arrays) needs a key.

Related

how to fix Deserialise object ignoring 0 in the starting of the number , but i want 0 to be as it is

var crmData = (JObject)JsonConvert.DeserializeObject(metaData.MetaData);
in above expression
metaData.MetaData contains correct values from UI as shown below
metaData.MetaData = "{ ApplicationFields : { folderId : 3633, reasonCodes: [01,02] }}"
but after JsonConvert the crmData contains below value
crmData = {{
"ApplicationFields": {
"folderId": 3633,
"reasonCodes": [1,2]
}
}}
as you can see reasonCodes values has been converted from 01 to 1 and 02 to 2.
how to avoid conversion. i want same values in crmData also.
It's not clear why you care about those leading zeros. As pointed out in the comments they are meaningless when using numbers. So if you really need them, change the JSON to use strings instead:
reasonCodes: ["01", "02"]
Alternatively, deserialise into a proper C# class and define the type as string:
public class Root
{
public Foo ApplicationFields { get; set; }
}
public class Foo
{
public int FolderId { get; set; }
public string[] ReasonCodes { get; set; }
}
And deserialise like this:
var result = JsonConvert.DeserializeObject<Root>(Json);
Console.WriteLine(string.Join(", ", result.ApplicationFields.ReasonCodes));
//Output:
// 01, 02
A leading zero is invalid for numbers in in JSON:
number = [ minus ] int [ frac ] [ exp ]
[...]
int = zero / ( digit1-9 *DIGIT )
You can have either a zero or a non-zero starting digit in a number. You might be able to solve this by using a custom converter.

Weird JSON Parsing situation with C#

I have a very strange situation with a customer's JSON. They send an array of objects named as the ID (which is a number) :
Instead of the expected object name allowing for a simple parsing, such as "amenity".
How can we parse this into a List of objects containing ID and Name? Here's the exact JSON text:
"amenities":{
"2194":{
"id":"2194",
"name":"Breakfast for 2"
},
"2192":{
"id":"2192",
"name":"Free WiFi"
}
}
And there are other case when we have more fields , not only id, and name inside each object
"amenities":{
"2194":{
"id":"2194",
"name":"Breakfast for 2",
"validto" : "2022-10-30"
},
"2192":{
"id":"2192",
"name":"Free WiFi",
"validto" : "2022-10-30"
}
}
Thank you all!!!
You need two classes, one to be the main(Class1) where the json will be converted into and another class(Class2) for the object in the array. Then you can convert the dictionary in the main into a List of Class2 values of the dictionary.
public class MyClass1{
public Dictionary<string,MyClass2> amenities;
}
public class MyClass2{
public string id;
public string name;
public string validto;
}
First deserialize into MyClass1, then get the Values from the Dictionary and turn into List.
List<MyClass2> list = JsonConvert.DeserializeObject<MyClass1>(jsonstring).amenities.Values.ToList()

How can I deserialize json array?

I have json and an array inside it what looks like:
{
"data" : [
[int],
[...],
[..n]
]
}
Can I get array from "data" using JsonUtility? Or any other way?
For now, I can get "data" using following code:
[System.Serializable]
public class ObjectProperties
{
public int[] data;
public string color;
}
public void LoadFromJson()
{
objectProperties = JsonUtility.FromJson<ObjectProperties>(File.ReadAllText(Application.streamingAssetsPath + "/CubeSettings.json"));
}
And I can get any data but array I need.
In case the structure actually is e.g.
{
"data" : [
[1],
[2],
[3]
]
}
This is a nested array int[][] (an array where each element is an array itself).
So either the JSON should rather look like
{
"data" : [
1,
2,
3
]
}
or - if changing the JSON is not an option for you - your c# structure rather has to be
[System.Serializable]
public class ObjectProperties
{
public int[][] data;
public string color;
}
BUT such nested arrays are not supported by the built-in JsonUtility (see Script Serialization).
For this you would need to use a different library like e.g. Newtonsoft .NET JSON (available as a Package via the Package Manager)
var json = File.ReadAllText(Application.streamingAssetsPath + "/CubeSettings.json"));
var objectProperties = JsonConvert.DeserializeObject<ObjectProperties>(json);
This also means the field will not be visible/editable in the Inspector and will not be saved together with the scene or prefabs in Unity.
I assume 'data' is array itself, but not array of array.
So it should be
{"data":[1,2,3],"color":"red"}
Also you should define get/set to include fields into serialization:
[System.Serializable]
public class ObjectProperties
{
public int[] data { get; set; }
public string color { get; set; }
}
Now you can run it:
var objectProperties = JsonSerializer.Deserialize<ObjectProperties>(...);

Import json not parsing the data

I am trying to make a json file with all the bonus characteristic you get per level.
Json is like this :
{
"0": {
"Armor": 1,
"Strenght": 1,
"Mana": 2,
"Power": 1,
"Health": 1
},
"1": {
"Armor": 1,
"Strenght": 1
}
}
I then call a loader :
struct LevelBonus
{
int Power;
int Mana;
int Strenght;
int Armor;
int Health;
}
Dictionary<string, LevelBonus> statsPerLevel;
statsPerLevel = FileLoaderManager.instance.LoadJSONData<Dictionary<string, LevelBonus>>("PlayerStats/level.json");
And somewhere else there is
public T LoadJSONData<T>(string path)
{
string filePath = Path.Combine(Application.streamingAssetsPath, path);
if (File.Exists(filePath))
{
string dataAsJson = File.ReadAllText(filePath);
T loadedData = JsonUtility.FromJson<T>(dataAsJson);
return loadedData;
}
else
{
Debug.LogError("Cannot load game data!");
return default(T);
}
}
My Data is loaded, but not parsed correctly. Basically, no error, but no data returned event tho the file is read and until
T loadedData = JsonUtility.FromJson<T>(dataAsJson);
I can read the data correctly as string. but that FromJson return nothing
What I am missing ?
EDIT : https://answers.unity.com/questions/1583163/importing-data-from-json.html?childToView=1583169#comment-1583169
What I pretty much always do when loading Jsons is never ever write them by hand. I create an instance of of what I'll want to write in memory first, than SAVE to json - to make sure the field layout is exactly as expected by the serialiser - its easy to write a json that is valid, but makes no sens when mapped to a C# class
In your case the answer is simple. in Json structure you have
{ field_name : field_value }
pairs. But when it says "1":value, it won't ever deserialize, becuase the name of the field is "1", which is not a valid field name in C# (it has to start with a letter). The definition object to which you desrialize would have to look like
class MyStats
{
public int Armor;
public int Strenght;
public int Mana;
public int Power;
public int Health;
}
I imagine this is rougly right, however to deserialize your example, your container object would need to be defined like this (which is invalid)
class MyContainerObject
{
public MyStats 1; // ERROR: INVALID FIELD NAME !!
public MyStats 2; // ERROR: INVALID FIELD NAME !!
}
It is not returning an error as the Json is valid, and the parser just skips fields that don't match the class definition you are using.
Regading the use of arrays you can either hack a wrapper extension (as suggested by Dharmashree) which is a bit quirky (JsonUtility needs to know the concrete class to which it is deserialising and it can't go directly to array or list so for example:
[
{"a": 1 },
{"b": 1 },
{"c": 1 }
]
while being a valid json, it will not be parsed by JsonUtility (raw, anonymous array), however this will
{
"MyStats": [
{ "a": 1 },
{ "b": 2 },
{ "c": 1 }
]
}
you can structure your data to contain the array within a container object, so your main object could be defined as:
class MyContainerObject
{
public MyStats[] stats;
}
Access to your elements is then via myList[index]
Anwyays, I will again highliy recommending starting with WRITING a json representing your structure, checking if that deserialising works as expected, and only then edit the file by hand.
Try to use array of Json. You can follow this sample here.
https://www.newtonsoft.com/json/help/html/ToObjectComplex.htm
Not able to comment so mentioning in answer.
The Person class used in NewtonSoft Documentation should have following structure.
public class Person
{
public string Name {get;set;}
}

Deserialize array in JSON into class/object

I'm trying to store JSON data into a class. I could deserialize my otherJSON string into class by: var ser = JsonConvert.DeserializeObject<ClsResult>(myJSON); before I got stuck with array.
{
\"Test\": [{
\"FirstBool\":1,
\"aString\":\"hello\"
}]
}
This is my class for JSON:
public class Test
{
[JsonProperty("FirstBool")]
public bool FirstBool { get; set; }
[JsonProperty("aString")]
public string aString { get; set; }
}
public class ResultObject
{
[JsonProperty("Test")]
public List<Test> Test { get; set; }
}
How I deserialize my non-array JSON:
var ser = JsonConvert.DeserializeObject<ResultObject>(myJSON);
What changes do I need to make it work again?
Edited answer
Your json string as I've noticed later contains object named Test which is basically an array of objects ( object[] ).
As you can see from the json string :
{
"Test": [{
"FirstBool" : 1,
"aString" : "hello"
}]
}
[ means that json object begins an array type and ] means that json object ended an array type.
{ means that json object begins an object type and } means that json object ended an object type.
Which in your case will require to make kind of a custom deserializer using existing methods from Newtonsoft.Json library.
Example for the Test object could be :
JObject obj = JObject.Parse(jsonString);
// now your obj contains field named "Test" that is of type object[]
// to retrieve informations you have to select "Test" token
JToken testToken = obj.SelectToken("Test");
// your token contains now something like " [{ "FirstBool" : 1, "aString" : "hello" }]"
// which basically is an array
// meaning that you have to iterate through this
foreach(var child in token.Children())
{
// and convert it to a Test object
Test test = JsonConvert.DeserializeObject<Test>(child.ToString());
// test now is fully deserialized object
}
Deserialize it as a list:
JsonConvert.DeserializeObject<List<Test>>(json);
...instead of a wrapper object.

Categories