How can I deserialize json array? - c#

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>(...);

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.

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.

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.

How should one interpret this JSON structure?

I've just started to work with JSON and after having read a few articles, I'm still unclear if I'm looking at an array, list or just an object. It looks like this.
{
"list": [{
"fields": {
"id": "9222115557374550596",
...
},
},
{
"fields": {
"id": "9222115557374550597",
...
},
}],
"paging": {
"pageCurrent": 0,
"itemMin": 0,
"itemMax": 2,
"maxNextPages": 0,
"pageSize": 100
}
}
I'd like to deserialize it to be a list (or IEnumerable) of objects typed so that there's an Id property (perhaps not all fields have to be parsed in to the object).
When I try to do that using the following code:
List<Some> somes = JsonConvert.DeserializeObject<List<Some>>(dataAbove);
class Some { public String Id { get; set; } }
I get a long error message about me not being using the correct type and array and a bunch of other stuff that makes me confused. Am I on the right track or did I totally went off and got lost?!
I understand it's something with the list at the root. But what?! Or at least - what should I google for?!
Cannot deserialize the current JSON object (e.g. {\"name\":\"value\"}) into type 'System.Collections.Generic.List`1[ScriveProxy.Template]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.\u000d\u000aTo 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.\u000d\u000aPath 'list', line 1, position 8."
It can't be this one because the outer brackets are curly not squary...
In this solution, we end up with a single object, not an array, so it's not what I'm aiming for neither.
In your case, "list" is an array of "fields" objects.
"paging" is an object.
Both "list"` and "paging"` are in an un-named root object.
Working dotNetFiddle: https://dotnetfiddle.net/4qLTvq
See the output in the console pane of the fiddle above.
Here's How you should declare your Classes for Deserializing this particular JSON into C# Classes.
public class Fields
{
public string id { get; set; }
}
public class TheFields
{
public Fields fields { get; set; }
}
public class Paging
{
public int pageCurrent { get; set; }
public int itemMin { get; set; }
public int itemMax { get; set; }
public int maxNextPages { get; set; }
public int pageSize { get; set; }
}
public class RootObject
{
[Newtonsoft.Json.JsonPropertyAttribute("list")]
public List<TheFields> FieldsList { get; set; }
public Paging paging { get; set; }
}
And here's how you would deserialize the whole thing.
var rootObject = JsonConvert.DeserializeObject<RootObject>(jsonString);
Since List is a keyword, and to avoid confusion and collision, I changed it's Name to FieldsList and also renamed the List class to TheFields class. You may choose any other name(s) that you feel is appropriate.
Explanation on Object vs Array
An object is an unordered set of name/value pairs. An object begins with { (left brace) and ends with } (right brace). Each name is followed by : (colon) and the name/value pairs are separated by , (comma).
An array is an ordered collection of values. An array begins with [ (left bracket) and ends with ] (right bracket). Values are separated by , (comma).
Source: http://www.json.org/
If it starts with { it's an object.
If it starts with [ it's an array.

Categories