Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question JsonConvert.Deserialize of List not working on Android...

Discussion in 'Scripting' started by IL_Olof, Sep 22, 2023.

  1. IL_Olof

    IL_Olof

    Joined:
    May 18, 2018
    Posts:
    2
    I'm trying to parse an array of a custom class from a server response using NewtonSoft.Json. It works fine in the Unity Editor, and when building for iOS, but when I'm building for Android it fails with this error in runtime:

    2023/09/22 14:38:53.445 23225 23279 Error Unity JsonSerializationException: Unable to find a constructor to use for type IllusionLabs.Netcode.NetcodeManager+GetLatestResponse. A class should either have a default constructor, one constructor with arguments or a constructor marked with the JsonConstructor attribute. Path '[0].startup_date', line 1, position 17.

    My GetLatestResponse class is this simple class:

    private class GetLatestResponse {
    public String region;
    public Int64 startup_date;
    public String server_ip;
    }

    And I try to read it like this:
    var body = JsonConvert.DeserializeObject<List<GetLatestResponse>>(bodyString);

    I tried to add an empty default constructor, and even tried to mark it:
    private class GetLatestResponse {
    [JsonConstructor]
    public GetLatestResponse() { }
    public String region;
    public Int64 startup_date;
    public String server_ip;
    }

    but it still fails with the same error. Also tried to make it a public standalone class instead of an inner class, still does not work.

    Both iOS and Android players use .NET 2.1 and ILCPP so I can't understand what the difference would be and why it wouldn't work on Android while working fine on iOS (and in Unity Editor)....

    Anyone has any idea what might go wrong?
    NewtonSoft version is com.unity.nuget.newtonsoft-json@3.2.1
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,563
    Did you check the constructor requirements as listed in the error message? You didn't mention it.

    Otherwise, code stripping might be another potential thing to look at.

    Not sure what kind of object that thing is but...

    When loading, you can never re-create a MonoBehaviour or ScriptableObject instance directly from JSON. The reason is they are hybrid C# and native engine objects, and when the JSON package calls
    new
    to make one, it cannot make the native engine portion of the object.

    Instead you must first create the MonoBehaviour using AddComponent<T>() on a GameObject instance, or use ScriptableObject.CreateInstance<T>() to make your SO, then use the appropriate JSON "populate object" call to fill in its public fields.
     
    Bunny83 likes this.
  3. IL_Olof

    IL_Olof

    Joined:
    May 18, 2018
    Posts:
    2
    The error messages tells me it needs a default constructor. Or a constructor marked with [JsonConstructor] But adding one does not make the error message go away. The class I try to deserialize is exactly the one I show in my question, there are no MonoBehaviours or any other base class involved.

    The weird thing is it works fine in Unity Editor and in iOS, only on Android it fails.

    And after more testing I've found the code also works fine when building for Android in another project using my netcode package. So I'm guessing what goes wrong is some of the many other Android dependencies the failing project uses. It pulls in a lot of dependencies such as firebase, google gaming services, google auth, etc, so I'm guessing something collides there.

    My current work-around is to stop using NewtonSoft and use the slightly-less-convenient JsonUtility from Unity. Which I guess is fine, only issue is that it doesn't support to deserialize json arrays without wrapping them in a json object. But I guess my server API should return an object as a reply anyway instead of an array to follow best practices in REST
     
    Last edited: Sep 26, 2023
  4. Henry_Xie

    Henry_Xie

    Joined:
    May 30, 2020
    Posts:
    4
    I get the same problem today, totally like yours, the code works fine on Editor but get error on android.
    Kurt's answer do help me, I find out the constructor is striped when building with android platform. I use [UnityEngine.Sripting.Preserve] with my constructor, problem is solved then. Hope that will help you if you still want to use NewtonSoft instead of JsonUtility.
    https://docs.unity3d.com/ScriptReference/Scripting.PreserveAttribute.html
    Code (CSharp):
    1. class MyJsonClass
    2. {
    3.     [JsonConstructor]
    4.     [UnityEngine.Scripting.Preserve]
    5.     public MyJsonClass(){}
    6.         ...
    7. }
     
    Bunny83 likes this.