- Home /
JSON into Unity Class
Hello,
I am retrieving a JSON message dynamically from an external source. Its a message list;
{
"conversation":{
"-LD8kInJ39jHQfrbjz34":{
"message":"msg1",
"read":false,
"sender":"X8oNADtJmOVSouYNU450d",
"timestamp":"05/22/2018 22:28:52"
},
"-LDBzfk8W-DnGn9dMptw":{
"message":"msg2",
"read":false,
"sender":"X8oNADtJmOVSouYNU450d",
"timestamp":"05/23/2018 13:34:54"
},
"-LDBzgy9gfQTBk1hi0MT":{
"message":"msg3",
"read":false,
"sender":"X8oNADtJmOVSouYNU450d",
"timestamp":"05/23/2018 13:34:59"
}
}
}
I need to then convert this into an Object-Class within Unity. Usually, I do this by using Unity's built in JsonUtility.FromJson.
My Class is a List, within another Class that actually holds the structure.
[System.Serializable]
public class ConversationClass{
public string message;
public string sender;
public string timestamp;
public bool read;
}
The problem is the generated index keys; "-LD8kInJ39jHQfrbjz34" for example. As these break the List array as an index, and I get Unexpected node type.
Any suggestions?
Is there a quick, easy way in which I can reference the keys, and then replace with "0", "1", "2", etc ?
I think the problem is that the JSON utility built into Unity is not general purpose, that's why it cannot handle the keys, nor can you modify the nodes.
As the documentation suggests, try a more sophisticated JSON parser implementation. $$anonymous$$aybe SimpleJSON would be good enough, or you can adapt it to your purposes.
Answer by oliver-jones · May 24, 2018 at 08:34 AM
I accomplished this using SimpleJSON in the end; http://wiki.unity3d.com/index.php/SimpleJSON
I basically just serialised it myself;
var N = JSON.Parse(_json);
for(int i = 0; i < N["conversation"].Count; i++){
MessageClass.Message.ConversationClass _conversation = new MessageClass.Message.ConversationClass();
_conversation.message = N["conversation"][i]["message"].Value;
_conversation.sender = N["conversation"][i]["sender"].Value;
_conversation.timestamp = N["conversation"][i]["timestamp"].Value;
_conversation.read = N["conversation"][i]["read"].AsBool;
_Messages.Contents.conversation.Add( _conversation );
}
Answer by hugopok · May 23, 2018 at 04:26 PM
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
[Serializable]
public class Wrapper
{
public List<ConversationClass> conversation = new List<ConversationClass> { new ConversationClass(),new ConversationClass(),new ConversationClass() };
}
[Serializable]
public class ConversationClass
{
public string message;
public string sender;
public string timestamp;
public bool read;
}
public class Deserialize : MonoBehaviour {
public string path;
// Use this for initialization
void Start ()
{
var json = JsonUtility.ToJson(new Wrapper(),true);
path = Application.dataPath + "/json.json";
System.IO.File.WriteAllText(path,json);
}
// Update is called once per frame
void Update () {
}
}
If you put your json in json viewer is read like a class, conversation is a class and not a list, so if you want to have a list you should have a wrapper class, and into this, a list of conversation class. Your key now are variable. you should insert the key into a conversation class, in this way you can retrieve your key without problem
Hello, thanks for your reply, but I think you misunderstood my question. I understand the List wrappers, but my issue is that I cannot serialise the nodes with the unique-ids.
Answer by tarahugger · May 24, 2018 at 09:34 AM
Why something so mature as serialization has to be such a pain here with Unity is very frustrating. I'd recommend you check out Json.Net - there are multiple free versions on the store.
You will be able to find lots of help for it on StackOverflow/Google. Unfortunately these unity versions are a little bit behind the offical versions and so are lacking a few features, but its still lightyears ahead of anything else, even Microsoft has adopted it as the standard for .Net Core.
Here's my current code, for underscore formatting.
using Newtonsoft.Json;
using System.Text.RegularExpressions;
using Newtonsoft.Json.Serialization;
namespace BackendSystem
{
public interface ISerializationProvider
{
T Deserialize<T>(string text);
string Serialize<T>(T obj);
}
public class BackendSerializer : ISerializationProvider
{
public BackendSerializer()
{
JsonConvert.DefaultSettings = () => new JsonSerializerSettings
{
ContractResolver = new UnderscorePropertyNamesContractResolver(),
NullValueHandling = NullValueHandling.Ignore
};
}
public T Deserialize<T>(string text)
{
return JsonConvert.DeserializeObject<T>(text);
}
public string Serialize<T>(T model)
{
return JsonConvert.SerializeObject(model);
}
private class UnderscorePropertyNamesContractResolver : DefaultContractResolver
{
protected override string ResolvePropertyName(string propertyName)
=> Regex.Replace(propertyName, @"(\w)([A-Z])", "$1_$2").ToLower();
}
}
}
namespace BackendSystem
{
public static class Backend
{
public static ISerializationProvider Serializer { get; set; } = new BackendSerializer();
}
}
And use it...
var errorResponse = Backend.Serializer.Deserialize<ErrorResponse>(www.downloadHandler.text);
another example.
result.ResponseSize = www.downloadedBytes;
result.Received = DateTime.Parse(www.GetResponseHeader("Date"));
result.StatusCode = (HttpStatusCode) www.responseCode;
result.Value = Backend.Serializer.Deserialize<T>(www.downloadHandler.text);
etc
var data = Backend.Serializer.Serialize(new RequestModel
{
Provider = o.Provider,
AccessToken = o.Token,
Resource = o.Resource ?? Backend.Options.ResourceName,
});
EDIT: Just realized that i didnt answer your question. You can do what you want with Json.Net like this.
[System.Serializable]
public class ConversationClass
{
public string message;
public string sender;
public string timestamp;
public bool read;
}
void Start()
{
var json = @"{
""conversation"":{
""-LD8kInJ39jHQfrbjz34"": {
""message"":""msg1"",
""read"":false,
""sender"":""X8oNADtJmOVSouYNU450d"",
""timestamp"":""05/22/2018 22:28:52""
},
""-LDBzfk8W-DnGn9dMptw"": {
""message"":""msg2"",
""read"":false,
""sender"":""X8oNADtJmOVSouYNU450d"",
""timestamp"":""05/23/2018 13:34:54""
},
""-LDBzgy9gfQTBk1hi0MT"": {
""message"":""msg3"",
""read"":false,
""sender"":""X8oNADtJmOVSouYNU450d"",
""timestamp"":""05/23/2018 13:34:59""
}
}
}";
var jsonObject = JObject.Parse(json);
var conversationsEntries = jsonObject["conversation"].Children();
var conversations = conversationsEntries.Select(t => t.FirstOrDefault()?.ToObject<ConversationClass>());
}
Answer by Tobychappell · May 24, 2018 at 09:52 AM
Instead of converting the conversations into a List(ConversationClass) you could try converting it into a Dictionary(string, ConversationClass) . If that works it seems the easiest/simplest solution and should only require a few lines of code to be changed.
Your answer
![](https://koobas.hobune.stream/wayback/20220612163253im_/https://answers.unity.com/themes/thub/images/avi.jpg)