Deserialize nested objects with JsonUtility - c#

I would like to deserialize my json files holding information about levels. Given this example .json file called 1.json
{
"name": "Level One",
"map": [
[{
"groundTexture": "grass",
"cellType": "empty",
"masterField": null,
"worldObjects": [{
"worldObjectType": "player",
"rotation": 90
}]
},{
"groundTexture": "grass",
"cellType": "obstacle",
"masterField": null,
"worldObjects": [{
"worldObjectType": "tree",
"rotation": 0
}]
}],[{
"groundTexture": "grass",
"cellType": "campFire",
"masterField": null,
"worldObjects": [{
"worldObjectType": "campfire",
"rotation": 270
}]
},{
"groundTexture": "grass",
"cellType": "related",
"masterField": {
"x": 1,
"y": 0
},
"worldObjects": []
}]
]
}
I would like to convert the data from that file to a class object holding all the data needed to create a level during runtime. I created a reader which only reads the file content
public class LevelReader : MonoBehaviour
{
private string levelBasePath;
private void Awake()
{
levelBasePath = $"{Application.dataPath}/ExternalFiles/Levels";
}
public string GetFileContent(string levelName)
{
string file = $"{levelName}.json";
string filePath = Path.Combine(levelBasePath, file);
return File.ReadAllText(filePath);
}
}
and a mapper which maps the json string to a LevelInfo object.
public class LevelMapper : MonoBehaviour
{
private void Start()
{
// DEBUGGING TEST
LevelReader levelReader = GetComponent<LevelReader>();
string levelContent = levelReader.GetFileContent("1");
LevelInfo levelInfo = MapFileContentToLevelInfo(levelContent);
Debug.Log(levelInfo.cells);
}
public LevelInfo MapFileContentToLevelInfo(string fileContent)
{
return JsonUtility.FromJson<LevelInfo>(fileContent);
}
}
The following structs just help to create an object containg all the level data:
[Serializable]
public struct LevelInfo
{
public string name;
public LevelCell[][] cells;
}
[Serializable]
public struct LevelCell
{
public string groundTexture;
public string cellType;
public Vector2? masterField;
public LevelWorldObject[] worldObjects;
}
[Serializable]
public struct LevelWorldObject
{
public string worldObjectType;
public int rotation;
}
When starting the application the mapper runs and loops through the data object. Unfortunately the cells are null. How can I deserialize the file correctly?

In LevelInfo structure you have field "cells" but in Json - "map". They must be the same.
JsonUtility can't serialize/deserialize multidimensional arrays.
https://answers.unity.com/questions/1322769/parsing-nested-arrays-with-jsonutility.html
https://docs.unity3d.com/Manual/script-Serialization.html
I believe you can change your data structures or use another serializer.

Related

How do I get info from an object with an array of objects in a json for Unity?

I have a JSON file setup as such
{
"cards": [
{
"id": "sand_bags",
"type": "Structure",
"name": "Sand Bags",
"values": [
{
"civilian": 1,
"fiend": -1
}
],
"effectTexts": [
{
"civilian": "Add +1 to your BUNKER.",
"fiend": "Send any CIVILIAN'S +1 STRUCTURE to the SCRAPYARD."
}
],
"flavorTexts": [
{
"civilian": "They're just heavy bags with sand. Not much else to say, but they'll slow down an attack from a fiend. Good luck, you'll need it!",
"fiend": "You've spotted a pretty bad STRUCTURE in this BUNKER. Time to do some damage."
}
],
"staysOnField": [
{
"civilian": true,
"fiend": false
}
],
"amountInDeck": 5
}
]
}
I also have a Cards script
[Serializable]
public class Cards
{
public Card[] cards;
}
[Serializable]
public class Card
{
public string id;
public string type;
public string name;
public int amountInDeck;
}
public class Values
{
public int civilian;
public int fiend;
}
I then have a CardEffects script that I'm using for my functions.
public class CardEffects : MonoBehaviour
{
public TextAsset jsonFile;
public Values values;
void Start()
{
Cards cardsInJson = JsonUtility.FromJson<Cards>(jsonFile.text);
foreach (Card card in cardsInJson.cards)
{
Debug.Log("Card name: " + card.name + " with " + values.civilian + " in the deck.");
}
}
}
I have searched all over trying to figure out how to even get the array of objects of "values". I got this far and the value printed is always 0 regardless of the information in "values" in the JSON. If I make the class Serializable, I'm able to change the values and it works but I want the values to be whatever they were declared as in the JSON. Is there a better way to do this?
Please keep in mind I'm new to C# and Unity. I usually code in JS in which using JSON files are no big deal for me and thought it was the best way to go.
Your json and your classes doesn't match. Not only that your json isn't even valid Json. Below I will give you your correct json and class.
{
"cards": [
{
"id": "sand_bags",
"type": "Structure",
"name": "Sand Bags",
"values": [
{
"civilian": 1,
"fiend": -1
}
],
"effectTexts": [
{
"civilian": "Add +1 to your BUNKER.",
"fiend": "Send any CIVILIAN'S +1 STRUCTURE to the SCRAPYARD."
}
],
"flavorTexts": [
{
"civilian": "They're just heavy bags with sand. Not much else to say, but they'll slow down an attack from a fiend. Good luck, you'll need it!",
"fiend": "You've spotted a pretty bad STRUCTURE in this BUNKER. Time to do some damage."
}
],
"staysOnField": [
{
"civilian": true,
"fiend": false
}
],
"amountInDeck": 5
}
] // <---- This was missing
}
For that Json this is how your card class will have to look like:
public Card
{
public string id { get; set; }
public string type { get; set; }
public string name { get; set; }
public Values[] values { get; set; }
public Values[] effectTexts { get; set; }
public Values[] staysOnField { get; set; }
public int amountInDeck { get; set; }
}
And your Values class have to look like this:
public class Values
{
public object civilian;
public object fiend;
}
I suggest MiniJson.
You can just copy paste the script to your project and you are ready to go.
The then can call Json.Deserialize(string json) passing your string in. For the case of an array you can do for example:
IList myJsonElements = (IList)Json.Deserialize(string json);
Find working snippet:
using System;
using Newtonsoft.Json;
namespace ConsoleApp3
{
class Program
{
static void Main(string[] args) {
string myJson = "{\"cards\": [{\"id\": \"sand_bags\",\"type\": \"Structure\",\"name\": \"Sand Bags\",\"values\": [{\"civilian\": 1,\"fiend\": -1}],\"effectTexts\": [{\"civilian\": \"Add +1 to your BUNKER.\",\"fiend\": \"Send any CIVILIAN'S +1 STRUCTURE to the SCRAPYARD.\"}],\"flavorTexts\": [{\"civilian\": \"They're just heavy bags with sand. Not much else to say, but they'll slow down an attack from a fiend. Good luck, you'll need it!\",\"fiend\":\"You've spotted a pretty bad STRUCTURE in this BUNKER. Time to do some damage.\"}],\"staysOnField\": [{\"civilian\": true,\"fiend\": false}],\"amountInDeck\": 5}]}";
var myJsonElements = MiniJSON.Json.Deserialize(myJson);
Console.WriteLine(myJsonElements.ToString());
string json = JsonConvert.SerializeObject(myJsonElements, Formatting.Indented);
Console.WriteLine(json);
Console.ReadLine();
}
}
}

Reading json with a key in unity 3d

Iam making a dictionary game in unity 3d. And i have a json file about all the definitions and examples of all vocabulary.Each word has key is the word it self ( which i highlighted). how can i get the value of each word(key). I have created an oject for json.
for example: i have a word "a cappella" it give me back:
a cappella
1: adverb
definition :without musical accompaniment
example : they performed a cappella
2 :adjective
definition :sung without instrumental accompaniment
example : they sang an a cappella Mass.
many thanks
Here is the model I use for the JSON
public class VocabularyModel : MonoBehavior
{
public string Word { get; set; }
public string WordId {get; set; }
public Meaning[] Meanings { get; set; }
public Label[] Labels { get; set; }
}
json String
{
"a cappella": {
"word": "a cappella",
"wordset_id": "5feb6f679a",
"meanings": [
{
"id": "492099d426",
"def": "without musical accompaniment",
"example": "they performed a cappella",
"speech_part": "adverb"
},
{
"id": "0bf8d49e2e",
"def": "sung without instrumental accompaniment",
"example": "they sang an a cappella Mass",
"speech_part": "adjective"
}
]
},
"AD": {
"word": "AD",
"wordset_id": "76c6ebfae9",
"meanings": [
{
"id": "4c21c72afa",
"def": "in the Christian era",
"speech_part": "adverb",
"synonyms": [
"A.D.",
"anno Domini"
]
}
]
},
"A.D.": {
"word": "A.D.",
"wordset_id": "b7e9d406a0",
"meanings": [
{
"id": "a7482f3e30",
"def": "in the Christian era",
"speech_part": "adverb",
"synonyms": [
"AD"
]
}
]
}
}
Are you using a library or you wrote the code yourself?
In the second case, I'd suggest to use Json.NET from Newtonsoft.
You can deserialize the JSON to a JObject and then treat it as if it was a dictionary.
To do this, you can structure your JSON in the following way:
{
"a_cappella" : {
"word" : "a cappella",
"wordId" : "123",
"meanings" : {...},
"labels" : {...}
}
"building" : {
"word" : "building",
"wordId" : "124",
"meanings" : {...},
"labels" : {...}
}
}
Then you deserialize into a JObject and search what you need:
var json = // here is your json string
var dictionary = JsonConvert.DeserializeObject(json);
if (dictionary.ContainsKey("a_cappella")){
return dictionary["a_cappella"].ToObject<VocabularyModel>();
}

JsonUtility in Unity is not working anymore. Why?

I'm trying to get a integer value from a Json that I GET from a server. I used JsonUtility from Unity libreries and It was working fine. And suddenly it is not parsing anymore.
All values returned are Null.
//SAMPLE CODE
SpinResult res = JsonUtility.FromJson<SpinResult>(download.downloadHandler.text);
spinValue = res.result;
//spinValue is always 0. It was working fine
//CLASS
[System.Serializable]
public class SpinResult
{
public int result;
}
//JSON
{
"data": {
"type": "",
"id": "",
"attributes": {
"server_seed": "",
"client_seed": "",
"result": 31,
},
"next_spin": {
"hashed_server_seed": "",
"client_seed": ""
}
}
}
I just need the integer "RESULT", in this case it should be 31 but the actual output is always 0. I check the Json everytime and its working perfectly fine.
I have not tested this, but try making your class look like this:
[System.Serializable]
public class SpinResult
{
public string type;
public string id;
public Attributes attributes;
}
[System.Serializable]
public class Attributes
{
public string server_seed;
public string client_seed;
public int result;
}
Then to get the value of result you would use:
int spinValue = res.attributes.result;

Deserialize JSON value without name

How can I deserialize a string in C# that only have values and no name. It looks like this: The problem is that this stream of string does not have name and uses array.
{
"result": {
"14400": [
[
1502985600,
262.18,
262.18,
257,
257,
1096.0131
],
[
1503000000,
257,
261.33,
254.8,
257,
1130.5897
]
],
"14405": [
[
1503014400,
258.03,
261.5,
257.01,
257.01,
520.7805
],
[
1503028800,
258,
260.98,
252.4,
259.56,
298.5658
],
]
]
}
}
Just create a class like
public class Root
{
public Dictionary<int,List<List<double>>> Result { get; set; }
}
and deserialize as
var res = JsonConvert.DeserializeObject<Root>(json);
I see it's an array, you could create a method to parse the class out of given JArray.
The Jason data
public void methpod()
{
string json ="Your jason value "
var factory = new Factory();
var suggest = factory.Create(json);
Console.WriteLine(suggest);
}
Make a class as suggested :
public class Factory
{
public Evan Create(string json)
{
var array = JArray.Parse(json);
string search = array[0].ToString();
string[] terms = array[1].ToArray().Select(item => item.ToString()).ToArray();
return new Evan{Search = search, Terms = terms};
}
}
and another
public class Evan
{
public string Search { get; set; }
public IEnumerable<string> Terms { get; set; }
public override string ToString()
{
return string.Format("Search={0},Terms=[{1}]",
Search, string.Join(",", Terms));
}
}
Tip
If you have JSON that you want to deserialize, and you don't have the class to deserialize it into, Visual Studio 2019 can automatically generate the class you need:
Copy the JSON that you need to deserialize.
Create a class file and delete the template code.
Choose Edit > Paste Special > Paste JSON as Classes.
The result is a class that you can use for your deserialization target

Create multiple objects from JSON file

I have a JSON file, that has many JSON objects:
[
"DIEM":
{
"Name":["A"],
"InRul":[]
},
"DOAN":
{
"Name":["A","B"],
"InRul":[]
},
"TAMGIAC":
{
"Name":["A","B","C"],
"InRul":[]
},
"TAMGIACVUONG":
{
"Name":["A","B","C"],
"InRul":[]
}
]
and, I have a class in C#:
class Content
{
public string Name;
public List<string> InRul;
}
How can I convert the JSON file above to objects in C#?
DIEM.Name //print Array [A]
DOAN.Name //print Array [A,B]
Thank so much!

Categories

Resources