- Home /
JSON problems and IEnumerator
I'm trying to get JSON data from a server using the WWW class and IEnumerator. I removed all mono behavior inheritance, tried to deserialize the json data to my class, but I end up with an error I've never seen before: ArgumentException: JSON parse error: The document root must not follow by other values. UnityEngine.JsonUtility.FromJson[T] (System.String json) (at C:/buildslave/unity/build/artifacts/generated/common/modules/JSONSerialize/JsonUtilityBindings.gen.cs:25) LoadDatabase+c__Iterator0.MoveNext () (at Assets/Scripts/LoadDatabase.cs:42) UnityEngine.SetupCoroutine.InvokeMoveNext (System.Collections.IEnumerator enumerator, System.IntPtr returnValueAddress) (at C:/buildslave/unity/build/Runtime/Export/Coroutines.cs:17)
I'm starting to wonder if the problem is that I'm using a CoRoutine. Could that be the case?
[System.Serializable]
public class VehicleIndex
{
public string ID{ get; set;}
public string Make{ get; set;}
public string Model{ get; set;}
public string Year{ get; set;}
public string Mileage{ get; set;}
}
Removed the constructor
[System.Serializable]
public class VehicleCollection
{
// public List <VehicleIndex>VehicleList{ get; set;}
public VehicleIndex[] vehicles;
}
Created a new class here.
Now the sticky point
public IEnumerator GetAllVehicles()
{
WWW VehicleData = new WWW ("http://localhost/CMVM/LoadVehicle.php");
yield return VehicleData;
Debug.Log (VehicleData.text);
This part shows all the JSON- all good
string json = VehicleData.text;
Not quite sure about this..
var cars = JsonUtility.FromJson<VehicleCollection>(json);
Can anyone give me a hand with this?
Thanks!
Answer by MacDx · Mar 15, 2018 at 11:37 PM
I think the problem is that your VehicleIndex class is using properties instead of fields. The documentation on JSONUtility never mentions properties. However, it does say that it only supports seralization of what Unity's serialization system does and I'm pretty sure properties are not supported since they don't show up on inspectors by default when you have them on MonoBehaviours.
Quoting the documentation:
Internally, this method uses the Unity serializer; therefore the type you are creating must be supported by the serializer. It must be a plain class/struct marked with the Serializable attribute. Fields of the object must have types supported by the serializer. Fields that have unsupported types, as well as private fields or fields marked with the NonSerialized attribute, will be ignored.
So I can think of 2 possible solutions to this problem.
1) This post on the forum says that you should try putting the [SerializeField] attribute on top of each of your properties. https://forum.unity.com/threads/jsonutility-and-properties.382526/
2) Don't use properties, use public fields instead. All of your properties are auto-implemented anyways (default get and set) and it doesn't look like you're gonna be using reflection or have virtual properties that will be overridden by child classes, so there wouldn't be any difference if you swapped them for fields. (This option is better IMO)
Hope this helps!
Edit: A third option would be to use a different JSON serialization library like Json.NET that does support property serialization by default.
Thanks $$anonymous$$axDx! Looks like I have more problems. I chose the third option and installed Newtonsoft Json for Unity. After deserializing, it gave the error
JsonReaderException: Additional text encountered after finished reading JSON content: {. Path '', line 1, position 87.
Newtonsoft.Json.JsonTextReader.Read () (at C:/Project/Github/Json.Net.Unity3D/src/Newtonsoft.Json/JsonTextReader.cs:408)
Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize (Newtonsoft.Json.JsonReader reader, System.Type objectType, System.Boolean checkAdditionalContent) (at C:/Project/Github/Json.Net.Unity3D/src/Newtonsoft.Json/Serialization/JsonSerializerInternalReader.cs:193)
Newtonsoft.Json.JsonSerializer.DeserializeInternal (Newtonsoft.Json.JsonReader reader, System.Type objectType) (at C:/Project/Github/Json.Net.Unity3D/src/Newtonsoft.Json/JsonSerializer.cs:823)
Newtonsoft.Json.JsonSerializer.Deserialize (Newtonsoft.Json.JsonReader reader, System.Type objectType) (at C:/Project/Github/Json.Net.Unity3D/src/Newtonsoft.Json/JsonSerializer.cs:802)
Newtonsoft.Json.JsonConvert.DeserializeObject (System.String value, System.Type type, Newtonsoft.Json.JsonSerializerSettings settings) (at C:/Project/Github/Json.Net.Unity3D/src/Newtonsoft.Json/JsonConvert.cs:865)
Newtonsoft.Json.JsonConvert.DeserializeObject[T] (System.String value, Newtonsoft.Json.JsonSerializerSettings settings) (at C:/Project/Github/Json.Net.Unity3D/src/Newtonsoft.Json/JsonConvert.cs:822)
Newtonsoft.Json.JsonConvert.DeserializeObject[T] (System.String value) (at C:/Project/Github/Json.Net.Unity3D/src/Newtonsoft.Json/JsonConvert.cs:759)
LoadDatabase+<GetAllVehicles>c__Iterator0.$$anonymous$$oveNext () (at Assets/Scripts/LoadDatabase.cs:44)
UnityEngine.SetupCoroutine.Invoke$$anonymous$$oveNext (System.Collections.IEnumerator enumerator, System.IntPtr returnValueAddress) (at C:/buildslave/unity/build/Runtime/Export/Coroutines.cs:17)
Couldn't find anything wrong with the json output from the WWW class.
{"ID":"1999SentraGXE","$$anonymous$$ake":"Nissan","$$anonymous$$odel":"Sentra","Year":"1999","$$anonymous$$ileage":"36000"}{"ID":"FAFP53U17A218749","$$anonymous$$ake":"Ford","$$anonymous$$odel":"SemiPanel","Year":"2015","$$anonymous$$ileage":"12"}{"ID":"G4G$$anonymous$$5EX1E9324742","$$anonymous$$ake":"$$anonymous$$ack","$$anonymous$$odel":"Dumpster","Year":"2012","$$anonymous$$ileage":"120"} UnityEngine.Debug:Log(Object) c__Iterator0:$$anonymous$$oveNext() (at Assets/Scripts/LoadDatabase.cs:37) UnityEngine.SetupCoroutine:Invoke$$anonymous$$oveNext(IEnumerator, IntPtr) This is the debug.log result.
So I went to see if the json was valid, but the JOSN Formatter said there were too many JSON root elements. Not sure how to fix it. Here is the PHP:
<?PHP
include('myconfig.php');
$resource = $connection->query('SELECT * FRO$$anonymous$$ vehicle');
while ( $rows = $resource->fetch_assoc() )
{
print json_encode($rows);
}
Thanks!
This is not valid json text:
{"ID":"1999SentraGXE","$$anonymous$$ake":"Nissan","$$anonymous$$odel":"Sentra","Year":"1999","$$anonymous$$ileage":"36000"}
{"ID":"FAFP53U17A218749","$$anonymous$$ake":"Ford","$$anonymous$$odel":"SemiPanel","Year":"2015","$$anonymous$$ileage":"12"}
{"ID":"G4G$$anonymous$$5EX1E9324742","$$anonymous$$ake":"$$anonymous$$ack","$$anonymous$$odel":"Dumpster","Year":"2012","$$anonymous$$ileage":"120"}
As those are three seperate objects without any structural connection. You can only have one "top level" Json value. Since you have several objects you may want to wrap them in an array.
Thanks Bunny. What can I do to the php, it's already using fetch_array, to make the structure sound? Or do I need to do it Unity-side?
I'm not that familiar with PHP but something like this should work i guess:
$resource = $connection->query('SELECT * FRO$$anonymous$$ vehicle');
$cars = array();
while ( $rows = $resource->fetch_assoc() )
{
$cars[] = $rows;
}
$data = array("vehicles"=>$cars);
print json_encode($data);
This should output something like this:
{
"vehicles":[
{
"ID":"1999SentraGXE",
"$$anonymous$$ake":"Nissan",
"$$anonymous$$odel":"Sentra",
"Year":"1999",
"$$anonymous$$ileage":"36000"
},
{
"ID":"FAFP53U17A218749",
"$$anonymous$$ake":"Ford",
"$$anonymous$$odel":"SemiPanel",
"Year":"2015",
"$$anonymous$$ileage":"12"
},
{
"ID":"G4G$$anonymous$$5EX1E9324742",
"$$anonymous$$ake":"$$anonymous$$ack",
"$$anonymous$$odel":"Dumpster",
"Year":"2012",
"$$anonymous$$ileage":"120"
}
]
}
So it's one object (your "VehicleCollection" object) with just one field: "vehicles". This field is an array or your car objects
Your answer
Follow this Question
Related Questions
Multiple Cars not working 1 Answer
Distribute terrain in zones 3 Answers
decode json response 1 Answer
JSON vs XML for Unity C# 1 Answer