How to parse Json files using Unity [duplicate] - c#

This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
In Unity (C#), why am I getting a NullReferenceException and how do I fix it? [duplicate]
(1 answer)
Closed 1 year ago.
Still on this issue, and I know this is an old post, but I'm also struggling to get C# to parse JSON.
I'm using Unity 2018.2.8f1, and VS 2019 (I also tried on VS 2017).
Here is my Json file (a really really simple one):
{
"glossary": {
"title": "example glossary"
}
}
And this is my C#:
using System;
using System.IO;
using UnityEngine;
[Serializable]
public class GlossaryRoot
{
public Glossary Glossary { get; set; }
}
[Serializable]
public class Glossary
{
public string title { get; set; }
}
public class Data_Manager : MonoBehaviour
{
private void Start()
{
string filePath = Path.Combine(Application.streamingAssetsPath, "Example.json");
string dataAsJSON = File.ReadAllText(filePath);
var myData = JsonUtility.FromJson<GlossaryRoot>(dataAsJSON);
string myTitle = myData.Glossary.title;
Debug.Log(myTitle);
}
}
I'm getting the error:
"NullReferenceException: Object reference not set to an instance of an object"
Any ideas on how to solve this issue? I've been looking for solutions, and tried a lot of things, but still with no success.
I know there are multiple issues similar to this one such as:
C#, Unity3D, JSON Parsing: Failing to parse JSON into C# object
But still I can't get it to work.
Even if I get delete the "gets and sets", I get "Null" in the console.
Any help is appreciated.
Thank you!

You names don't match it should be public Glossary glossary instead.
afaik Unity's Serializer (and therefore also the builtin JsonUtility) doesn't support (de)serialization of properties, rather use fields
so this should work
[Serializable]
public class GlossaryRoot
{
public Glossary glossary;
}
[Serializable]
public class Glossary
{
public string title;
}

Related

Parsing JSON into list [duplicate]

This question already has answers here:
Serialize and Deserialize Json and Json Array in Unity
(9 answers)
Closed 1 year ago.
So I was trying to parse the JSON data into list/array, but kinda stuck at the format like this.
I'm relatively new at JSON, so I'm not very good at processing those stuffs
Here's my code:
void processJsonData(string _url)
{
jsonDataClass jsnData = JsonUtility.FromJson<jsonDataClass>(_url); //_url is based on the Json text below
Debug.Log(jsnData.data);
}
I uses this code to see if it managed to get the data from it, but
it shows the error like this
The JSON looks like this:
[{"country":"Malaysia","sales":9244},
{"country":"Singapore","sales":3103},
{"country":"Japan","sales":1755},
{"country":"China","sales":7835},
{"country":"United States","sales":2755},
{"country":"United Kingdom","sales":8611},
{"country":"Australia","sales":3877}]
My jsonDataClass looks like this:
using System.Collections;
using System.Collections.Generic;
using System;
[Serializable]
public class jsonDataClass
{
public List<basicData> data;
}
[Serializable]
public class basicData
{
public string country;
public float sales;
}
Updated answer:
Apparently in Unity you can not directly deserialize collection/list/array with the built-in JsonUtility (thanks to #derHugo for the info), if you looking for quick and probably dirty solution, use below code:
List<basicData> jsnData = JsonUtility.FromJson<List<basicData>>("{\"data\":" + _url + "}");
And if you like to learn more, see: Serialize and Deserialize Json and Json Array in Unity and JSON Serialization

Pagination Newtonsoft.Json

A problem I've been running into recently is dealing with pagination of Json I receive from the server. I can work around some instances but would like a better approach. So the structure I receive here illustrates a problem I can run into:
Modules
{
ID
Title
Description
Lessons
{
edges
{
node
{
ID
}
}
}
}
So for the lessons array, the server inserts the edges and node elements because of the use of pagination. So what I would expect instead is:
Modules
{
ID
Title
Description
Lessons
{
ID
}
}
The main problem however with this is that it stops me being able to deserialize the object easily, i.e. I can't do this:
Modules[] modules = JsonConvert.DeserializeObject<Modules[]>(json, settings);
My Lesson and Module class for reference is just:
public class Lesson
{
public int ID;
}
[System.Serializable]
public class Module
{
public string ID;
public string Title;
public string Description;
public Lesson[] Lessons;
}
So just wondered if anyone else had come across a similar issue and what solutions they've done to work around it?
Your serialization should work just fine if you create concrete objects for 'edges' and 'node'.
I assume 'lessons' it an array of 'edge' object. 'edge' object contains the 'node' object, which has the property 'id'
So I worked out a bit of a workaround (sort of following Zero Cool's answer) which is to make generic Edges and Node classes. i.e.
[System.Serializable]
public class Edges<T>
{
public Node<T>[] edges;
}
public class Node<T>
{
public T node;
}
And then declare them where I am using Pagination. It's not lovely but works alright as I usually know what is/isn't paginated.
Would still be interested if there's a cleaner way.

How to implement Master/Detail classes using Generics and inheritance [duplicate]

This question already has answers here:
Casting List<T> - covariance/contravariance problem
(3 answers)
Closed 5 years ago.
I am writing the base classes for a Data Model using Generics. The base classes should support:
DetailClass with DetailKey (any type)
MasterClass with MasterKey (any type) and holding a List<DetailClass>
I would like to inherit from these 2 classes, whenever I have a Master/Detail relationship in my DM.
Here is the simplified code for the base classes:
class Master<TMKey, TDKey> {
public readonly TMKey MKey;
public readonly List<Detail<TMKey, TDKey>> Details;
public Master(TMKey mKey) {
MKey = mKey;
Details = new List<Detail<TMKey, TDKey>>();
}
}
class Detail<TMKey, TDKey> {
public readonly TDKey DKey;
public readonly Master<TMKey, TDKey> Master;
public Detail(TDKey dKey, Master<TMKey, TDKey> master) {
DKey = dKey;
Master = master;
}
}
I run into troubles with the compiler, when I try to inherit from these classes:
class Sub: Detail<int, DateTime> {
public DateTime Date { get { return DKey; } }
public string S;
public Main main { get { return (Main)Master; } }
public Sub(DateTime date, string s, Main main) : base(date, main) {
S = s;
}
}
class Main: Master<int, DateTime> {
public int MainId { get { return MKey; } }
public string M;
public List<Sub> SubDetails { get { return (List<Sub>)Details; } } //compiler error
public Main(int mKey, string m) : base(mKey) {
M = m;
}
}
Compiler Error:
Cannot convert type 'System.Collections.Generic.List<FlatFileStore.Detail<int, System.DateTime>>' to 'System.Collections.Generic.List<FlatFileStore.Sub>'
It seems the compiler doesn't realise:
Sub: Detail<int, DateTime>
Any suggestion how to work around this compiler limitation ?
How needs the DM classes be changed to avoid any compiler problems and achieve high performance (i.e. no copies of collections) ?
A working sample code would be appreciated.
Edit1: It is not possible to use a .ToList() solution (see answer below). There might be thousands of details, .ToList() could get called thousands of times and each time would create a new List with thousands of items.
Edit2: The original question seemed to be a duplicate of "Casting List - covariance/contravariance problem", so I rewrote it to explain better. The other question asks specifically how to make a copy of List and therefore all answers in that question answer how to make such a copy. My question now asks how the classes have to be designed to avoid the compiler problem without using copying with its huge performance problems. There are other solutions possible, like using IReadOnlyList<T>, which are not mentioned at all in the answers in that question. But there might be also other possibilities, like telling the Master class which Type to use for the collection it creates. Or another design might be possible. Or ...
This is to do with co/contravariance. One way around this is to cast using linq:
public List<Sub> SubDetails { get { return Details.Cast<Sub>().ToList(); } }
Other solutions and discussion are shown here: Casting List<T> - covariance/contravariance problem

I get a null reference on a property in one of my classes [duplicate]

This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 6 years ago.
Am using winforms in c# with visual studio 2015
This is my class
public class advmessage
{
public string[] message;
}
so then in the load event of form1 I do this
advmessage newadvmessage = new advmessage();
newadvmessage[1]="Hello";
and for that assignment, it throws the exception for null reference and says object reference not set to an instance of an object.
So if I have a class that does not need to be an array, everything works find, but on the ones that use arrays, is where it has the exception.
Also, I do not have a get set or return for any of the classes, and that might b the problem but yet when I added the { get; set; } in there it still had a problem. I could understand a null reference, if I referenced a null string, but I am just trying to set the message property that will be shown in a text box to the user.
Any help would be greatly appreciated.
public class advmessage
{
public advmessage(size)
{
message = new string[size];//or whatever size you want.
}
public string[] message;
}
advmessage newadvmessage = new advmessage(5);
newadvmessage.message[1]= "Hello";

Can I instruct Json.NET to deserialize, but not serialize, specific properties? [duplicate]

This question already has answers here:
Making a property deserialize but not serialize with json.net
(13 answers)
Closed 7 years ago.
I have an AngularJS + MVC 5 + Web API 2 app that allows users to manage collections of objects in the browser and commit all changes at once when a Save button is clicked. As changes are made, one or more properties are added to the JavaScript objects: IsAdded, IsUpdated, IsRemoved. The properties are checked server-side to determine what to do when persisting the model.
The model is served up using Json.NET via Web API, and the base class is:
public class CollectionItemViewModel : ICollectionItem
{
public bool IsAdded { get; set; }
public bool IsUpdated { get; set; }
public bool IsRemoved { get; set; }
}
This works great, but adds cruft to my serialized JSON. I can choose to not serialize these three properties with ShouldSerialize, but that also prevents them from deserializing.
public bool ShouldSerializeIsAdded()
{
return false;
}
public bool ShouldSerializeIsUpdated()
{
return false;
}
public bool ShouldSerializeIsRemoved()
{
return false;
}
Is it possible to deserialize, but not serialize, specific properties using Json.NET?
You should be able to just use the ShouldSerialize* methods as shown in the question. These only impact serialization, not deserialization.
The correct attribute is JsonIgnore.
[JsonIgnore]
public int Id {get;set;}
Source doc available here:
http://james.newtonking.com/archive/2009/10/23/efficient-json-with-json-net-reducing-serialized-json-size

Categories