This question already has answers here:
Serialize and Deserialize Json and Json Array in Unity
(9 answers)
Parse nested json in unity [duplicate]
(2 answers)
Closed 5 years ago.
I have the following problem: I'm trying to parse a nested JSON using the Unity JsonUtility, but if i'm logging one of the nested parameters i get Null as a result.
Here's the Json:
{
"basic": {
"name": "Demo Bow"
},
"effect": {
"damage": {
"stages": 3,
"one": 4,
"two": 10,
"three": 40
}
}
}
And here's my code:
public class Basic
{
public string name;
}
public class Damage
{
public int stages;
public int one;
public int two;
public int three;
}
public class Effect
{
public Damage damage;
}
public class RootObject
{
public Basic basic;
public Effect effect;
}
Edit: No its not a duplicate, cause I already removed the "{ get; set; }"
And heres the missing code.
public static RootObject CreateFromJSON(string json){
RootObject weapon = JsonUtility.FromJson <RootObject> (json);
return weapon;
}
Thanks for any help
You are missing the [System.Serializable] attribute on your classes, it is needed for JsonUtility to be able to serialize or deserialize your classes.
[System.Serializable]
public class Basic
{
public string name;
}
[System.Serializable]
public class Damage
{
public int stages;
public int one;
public int two;
public int three;
}
[System.Serializable]
public class Effect
{
public Damage damage;
}
[System.Serializable]
public class RootObject
{
public Basic basic;
public Effect effect;
}
Related
This question already has answers here:
.Net Core 3.0 JsonSerializer populate existing object
(8 answers)
Closed 12 months ago.
I want to import json data from within the class which is the target of the deserialization. Is this possible with System.Text.Json without additional mapping? Ideally I would use "this" instead of the generic type parameter. I know that is impossible, but is there a similar option? Here is my test code which works, because it creates the data object only to map it to the property. Ideally, I would not need to instantiate "Test" twice.
public class Test
{
public string? Bar { get; set; }
public void ImportJson(string payload)
{
var data = System.Text.Json.JsonSerializer.Deserialize<Test>(payload);
Bar = data?.Bar; // Don't want to map
}
}
string foo = "{ \"Bar\": \"baz\" }";
var t = new Test();
t.ImportJson(foo);
Console.WriteLine(t.Bar);
you can try something like this
string foo = "{ \"Bar\": \"baz\" }";
var t = new Test();
t.Deserialize(foo);
Console.WriteLine(t.Instance.Bar);
classes
public static class Util
{
public static void Deserialize<T>(this T obj, string json) where T : IImportJson<T>
{
obj.Instance=System.Text.Json.JsonSerializer.Deserialize<T>(json);
}
}
public class Test : ImportJson<Test>
{
public string? Bar { get; set;}
}
public interface IImportJson<T>
{
public T Instance { get; set; }
}
public class ImportJson<T>: IImportJson<T>
{
public T Instance { get; set; }
}
if class dosn't have many properies, it could be like this too
public interface IImportJson<T>
{
public void ImportJson (T obj);
}
public class Test : IImportJson<Test>
{
public string? Bar { get; set; }
public void ImportJson(Test test)
{
Bar=test.Bar;
}
}
This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Serialize and Deserialize Json and Json Array in Unity
(9 answers)
Closed 3 years ago.
I'm new to using Json and I cant figure out why data isn't deserializing. I tried many things and I don't know what the problem is.
First I need to get data from this link https://jsonplaceholder.typicode.com/users
and then i need to deserialize it. (Need to use REST request)
Whenever I wanna use any property it tells me its NULL "NullReferenceException: Object reference not set to an instance of an object"
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Networking;
using System.Net;
using System.IO;
public class Houses : MonoBehaviour
{
public GameObject Prefab;
void Update()
{
if (Input.GetKey(KeyCode.T))
{
onClick();
}
}
public void onClick()
{
UnityWebRequest request = UnityWebRequest.Get("https://jsonplaceholder.typicode.com/users");
RootObject[] rootObjects = JsonUtility.FromJson<RootObject[]>(request.downloadHandler.text);
//Debug.Log(request.downloadHandler.text);
//foreach (var item in rootObjects)
//{
// Debug.Log(item.id);
//}
//----------------------------------------------------------------------------------------
//Latitude is the Y axis, longitude is the X axis
//for (int i = 0; i < rootObjects.Length; i++)
//{
// float x = float.Parse(rootObjects[i].address.geo.lng);
// float y = float.Parse(rootObjects[i].address.geo.lat);
// Instantiate(Prefab, new Vector3(x, y, 0f), Quaternion.identity);
//}
}
}
//public class ListItems
//{
// //public RootObject[] rootObjects;
//public List<RootObject> rootObjects;
//}
[System.Serializable]
public class Geo
{
public string lat { get; set; }
public string lng { get; set; }
}
[System.Serializable]
public class Address
{
public string street { get; set; }
public string suite { get; set; }
public string city { get; set; }
public string zipcode { get; set; }
public Geo geo { get; set; }
}
[System.Serializable]
public class Company
{
public string name { get; set; }
public string catchPhrase { get; set; }
public string bs { get; set; }
}
[System.Serializable]
public class RootObject
{
public int id; //{ get; set; }
public string name { get; set; }
public string username { get; set; }
public string email { get; set; }
public Address address { get; set; }
public string phone { get; set; }
public string website { get; set; }
public Company company { get; set; }
}
I would be really grateful if someone could help me out.
EDIT:
So i made some changes. Turns out thanks to you guys i didnt give the UnityWebRequest time to get the data.
Now im getting a different error "ArgumentException: JSON must represent an object type."
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.Networking;
using System.Net;
using System.IO;
public class Houses : MonoBehaviour
{
public GameObject Prefab;
public string jsonURL;
void Update()
{
if (Input.GetKeyUp(KeyCode.T))
{
onClick();
}
}
public void processJsonData(string _url)
{
RootObject[] rootObjects = JsonUtility.FromJson<RootObject[]>(_url);
Debug.Log(rootObjects[0].id);
}
IEnumerator getData()
{
Debug.Log("Procesing data, please wait.");
//WWW _www = new WWW(jsonURL);
UnityWebRequest request = UnityWebRequest.Get("https://jsonplaceholder.typicode.com/users");
yield return request.SendWebRequest();
if (request.error == null)
{
processJsonData(request.downloadHandler.text);
}
else
{
Debug.Log("Oops something went wrong.");
}
}
public void onClick()
{
//----------------------------------------------------------------------------------------
//Latitude is the Y axis, longitude is the X axis
//for (int i = 0; i < rootObjects.Length; i++)
//{
// float x = float.Parse(rootObjects[i].address.geo.lng);
// float y = float.Parse(rootObjects[i].address.geo.lat);
// Instantiate(Prefab, new Vector3(x, y, 0f), Quaternion.identity);
//}
StartCoroutine(getData());
}
}
//public class ListItems
//{
// //public RootObject[] rootObjects;
//public List<RootObject> rootObjects;
//}
[System.Serializable]
public class Geo
{
public string lat;
public string lng;
}
[System.Serializable]
public class Address
{
public string street;
public string suite;
public string city;
public string zipcode;
public Geo geo;
}
[System.Serializable]
public class Company
{
public string name;
public string catchPhrase;
public string bs;
}
[System.Serializable]
public class RootObject
{
public int id;
public string name;
public string username;
public string email;
public Address address;
public string phone;
public string website;
public Company company;
}```
Untiy's JsonUtility is a relatively performant but also extremely limited serializer. It only supports serializing fields, while the objects you are trying to deserialize are entirely made up of properties, which it does not support.
(By the way, that Unity's default serializer doesn't support properties, is also why they don't show up in the editor while fields do.)
Since it doesn't know how to set the property, it doesn't, and the property remains with its default valuel. In the case of refrence types (string, Address, etc.) the default value is NULL, which makes trying to access them throw an exception.
All you have to do to fix this in your case is change the classes you want to deserialize so that this:
public class Geo
{
public string lat { get; set; }
public string lng { get; set; }
}
Becomes this:
public class Geo
{
public string lat;
public string lng;
}
Do that for all your classes, and you should be golden.
EDIT: As Philip B. Mentioned in his answer, you are also not using UnityWebRequest.Get correctly.
UnityWebRequest doesnt resolve immediatly, and you must either yield return... to it from inside a Unity Coroutine, or wait for it to resolve with a blocking loop like so:
UnityWebRequest request = UnityWebRequest.Get("https://jsonplaceholder.typicode.com/users");
request.SendWebRequest();
while (!request.isDone) {}
Of course this is considered very bad form, as it freezes the game untill the data is downloaded. However, under the hood Unity handles the downloads on background threads, so you won't be blocking the download itself while you wait.
You should also query the request to see if any errors came up so you can handle them if you want to, as you might also be having issues with the download itself.
if (request.isHttpError || request.isNetworkError)
{
//... handle errors here
}
else
{
RootObject[] rootObjects = JsonUtility.FromJson<RootObject[]>(request.downloadHandler.text);
}
However, I'd really recommend you use coroutines here as described in Unity's UnityWebRequest.Get documentation. If you're new to Unity Coroutines please read up, it's a valuable tool for Unity development.
EDIT 2: Per this answer JsonUtility doesn't support serializing an array as a top level object, so you'll have to wrap your array in an object first, and deserialize that. You'll also have to make the top level object in the json file an object that holds that array.
[Serializable]
public class Routes
{
public RootObject[] roots;
}
If you don't control the contents of the file, (and again this idea is coming from that excelent answer I linked to) you can do so with some string magic.
string jsonString = $#"{{""roots"":{request.downloadHandler.text}}}";
You are trying to access request.downloader.text which is NULL (hence the "NullReferenceException: Object reference not set to an instance of an object") since you didn't send your GET request.
If you follow this link on how to use UnityWebRequest.Get you will see that you need more than just UnityWebRequest.Get("Your_Url"); to get your JSON string from the URL.
Try the following :
public void onClick()
{
using (UnityWebRequest request = UnityWebRequest.Get("https://jsonplaceholder.typicode.com/users"))
{
request.SendWebRequest();
RootObject[] rootObjects = JsonUtility.FromJson<RootObject[]>(request.downloadHandler.text);
}
}
Hope this will help you.
This question already has answers here:
Serialize and Deserialize Json and Json Array in Unity
(9 answers)
Closed 5 years ago.
Here is my JSON file for testing purposes :
{"timestamp":4455518515,"profileId":"5asd15qwe11as2d12q1sd","profileName":"player01",
"textures":{"material":{"url":"http://materialurl.com/aksjd54854we5a4sd.png"}}}
I want to reach textures -> material -> url but i can't. Here is my code :
public class JsonTest : MonoBehaviour {
string json;
string path;
// Use this for initialization
void Start () {
path = Application.streamingAssetsPath + "/json.txt";
json = File.ReadAllText(path);
MaterialJson test = JsonUtility.FromJson<MaterialJson>(json);
Debug.Log(test.timestamp);
Debug.Log(test.profileId);
Debug.Log(test.profileName);
Debug.Log(test.textures);
}
}
[Serializable]
public class MaterialJson
{
public double timestamp;
public string profileId;
public string profileName;
public string textures;
}
There is no problem for first three variables. But textures returns null in debug log. I have no idea how can I take nested variables in textures. Is unity's JsonUtility capable of that ? I couldn't find any info on unity's documentation.
It's worked perfectly with the code below : (Thanks to #mrfreester)
[Serializable]
public class MaterialJson
{
public double timestamp;
public string profileId;
public string profileName;
public Textures textures;
}
[Serializable]
public class Textures
{
public Material material;
}
[Serializable]
public class Material
{
public string url;
}
Debug.Log(test.textures.material.url);
It looks like you're expecting textures to be a string here
public string textures;
However it's an object in your json.
You could create a Serializable class for each associated json object if you want it to work with your json in its current format. As stated in your comment:
[Serializable]
public class MaterialJson
{
public double timestamp;
public string profileId;
public string profileName;
Textures texture;
}
[Serializable]
public class Textures
{
Material material;
}
[Serializable]
public class Material
{
public string url;
}
Which would then be accessed like this:
Debug.Log(test.texture.material.url);
Method 1:
You can use this:
using (var ms = new System.IO.MemoryStream(Encoding.Unicode.GetBytes(json)))
{
System.Runtime.Serialization.Json.DataContractJsonSerializer deserializer = new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(MaterialJson));
MaterialJson test = (MaterialJson)deserializer.ReadObject(ms);
}
Method 2:
Thanks to Newtonsoft and JSON.Net, you can try this:
var test = JsonConvert.DeserializeObject<MaterialJson>(json);
and the MaterialJson class as below:
[Serializable]
public class MaterialJson
{
public double timestamp;
public string profileId;
public string profileName;
public texturesType textures;
public class texturesType
{
public materialType material;
public class materialType
{
public string url;
}
}
}
Now you can access the url property using: test.textures.material.url
my JSON looks like this:
{
"kind": "youtube#videoListResponse",
"etag": "\"sZ5p5Mo8dPpfIzLYQBF8QIQJym0/TOPzMxlQJUtRJBXHeKYMXsdEkHs\"",
"pageInfo":
{
"totalResults": 1,
"resultsPerPage": 1
},
"items":
[
{
"kind": "youtube#video",
"etag": "\"sZ5p5Mo8dPpfIzLYQBF8QIQJym0/BIVqr1Mkbule8othzWvZRor92wU\"",
"id": "QMNkWwq6L4Q",
"contentDetails":
{
"duration": "PT4M45S",
"dimension": "2d",
"definition": "hd",
"caption": "false",
"licensedContent": true,
"projection": "rectangular"
}
}
]
}
The formatting might be a bit off, sorry.
I tried creating a class like this:
public class VideoDetails
{
public string kind;
public string etag;
public string id;
public string duration;
public string definition;
public string caption;
public string licensedContent;
public string projection;
}
After that I deserialize the JSON file:
VideoDetailRead = JsonConvert.DeserializeObject<VideoDetails>(json);
but I only get "etag" and "kind". Nothing else. My question is: How do I read the data that's listed under "items"? This is my first time working with JSON and therefor I don't know much. Thanks for some answers.
Create a second object to model the children data. Provided the items property has also a child under contentDetails, you will also need another object to deserialize these properties.
public class VideoDetailsItem
{
public string kind;
public string etag;
public string id;
public VideoContentDetails contentDetails;
}
public class VideoContentDetails
{
public string duration;
public string definition;
public string caption;
public bool licensedContent;
public string projection;
}
And to the parent object add a List<VideoDetailsItem>.
public class VideoDetails
{
public string kind;
public string etag;
public List<VideoDetailsItem> items;
}
When deserializing JSON objects you have to mimic the JSON object structure in your object. Also, consider using properties instead of public fields to favor encapsulation in your data objects.
The properties you have listed are inside an array named items, so your object hierarchy has to match this:
public class VideoList
{
public string kind;
public string etag;
// etc...
public List<VideoDetails> items;
}
public class VideoDetails
{
public string kind;
public string etag;
public string id;
public string duration;
public string definition;
public string caption;
public string licensedContent;
public string projection;
}
Then:
var videos = JsonConvert.DeserializeObject<VideoList>(json);
This is because you aren't properly modeling the object structure. Right now, your JSON is structured like:
{baseInformation, VideoDetailsArray}
Thus you have to restructure your data object as
public class VideoDetails
{
//Base information
public string kind {get; set;}
public string etag {get; set;}
//...
public List<VideoDetails> {get; set;}
}
You have to define your class to match the structure of the JSON: in this case, you would define items as a list of a separate class which has the properties under it like duration etc. You should have your VideoDetails class nested inside another class that can wrap both objects in the JSON, and add another class for the contentDetails object.
One thing you can do is copy the JSON into your clipboard, open a new class file in Visual Studio, and go to Edit > Paste Special > Paste JSON as Classes. This will create the correct structure for you, and you can see how the nested classes in the JSON properly translate to C# classes.
i got this question i don't know is it possible or not.
so i am getting this json data
{
"data": {
"student_score": {
"time_elapsed": 10,
"right_moves": 20,
"wrong_moves": 10,
"score": 166
},
"average_score": {
"time_elapsed": 10,
"right_moves": 20,
"wrong_moves": 10,
"score": 166
},
"total_student_count": 1
},
"status": "success",
"time": 1379066567
}
i am able to coveting it to two class objects of these classes..
public class StudentAssignementScoreClassForCompAssn : ViewModelBase
{
private int _time_elapsed;
private int _right_moves;
private int _wrong_moves;
private int _score;
public int time_elasped
{
get
{
return _time_elapsed;
}
set
{
_time_elapsed = value;
RaisePropertyChanged("time_elapsed");
}
}
public int right_moves
{
get
{
return _right_moves;
}
set
{
_right_moves = value;
RaisePropertyChanged("right_moves");
}
}
public int wrong_moves
{
get
{
return _wrong_moves;
}
set
{
_wrong_moves = value;
RaisePropertyChanged("wrong_moves");
}
}
public int score
{
get
{
return _score;
}
set
{
_score = value;
RaisePropertyChanged("score");
}
}
}
second class is same as it is..but with different name..
so my problem is this..the structure of the json data is variable like data fields may be more or less..so is there any way that i automatically create class of this data and can bind all the fields of this class(automatically :))..means data filling and binding with the view that does not depend on how the json coming( i will have separate file for the details of json format) ..i think you are getting my issue..any kind of help like idea or different way of working with json (anything) is appreciated..sorry for my bad english :(
Look at this. http://jsonclassgenerator.codeplex.com/SourceControl/latest
Also see this SO answer: Deserialize JSON into C# dynamic object?
There are so many results:
search?q=dynamically+create+c%23+class+from+json
You need to create 2 more class like
public class YourClass
{
public DataClass data {get;set;}
public string status {get;set;}
public long time {get;set;}
}
public class DataClass
{
public StudentAssignementScoreClassForCompAssn student_score {get;set;}
public StudentAssignementScoreClassForCompAssn average_score {get;set;}
public int total_student_count {get;set;}
}
then use Newtonsoft.Json for conversion
JsonConvert.DeserializeObject<YourClass>(inputString)