Search Unity

  1. Good news ✨ We have more Unite Now videos available for you to watch on-demand! Come check them out and ask our experts any questions!
    Dismiss Notice

Serialization works well in editor but not on mobile

Discussion in 'Scripting' started by Maplod, Jan 4, 2020.

  1. Maplod

    Maplod

    Joined:
    Jul 6, 2014
    Posts:
    6
    im using WordPress API as a headless server for my app. at first I Deserialized the JSON as a dynamic object and everything was well, than I realized that I cant use dynamic for IL2CPP builds so I Deserialized it normally using :
    Code (CSharp):
    1.  [JsonExtensionData]
    2. public IDictionary<string, object> other;
    for the junk fields I dont need.

    for some reason everything works nicely in the editor but not on android (both mono and IL2CPP).
    I use Newtonsoft.Json.

    Code (CSharp):
    1.  var appData = JsonConvert.DeserializeObject<List<WP>>(response);

    this is the error I get from the Logcat

    Code (CSharp):
    1. InvalidOperationException: Sequence contains no elements
    2.   at System.Linq.Enumerable.First[TSource] (System.Collections.Generic.IEnumerable`1[T] source) [0x00010] in <718fce07ab1440e4a36674825fdaf808>:0
    3. Newtonsoft.Json.Serialization.DefaultContractResolver.SetExtensionDataDelegates (Newtonsoft.Json.Serialization.JsonObjectContract contract, System.Reflection.MemberInfo member) [0x00182] in <795d7d5f77dc40f5bc8e819adb0a4748>:0
    4. Newtonsoft.Json.Serialization.DefaultContractResolver.CreateObjectContract (System.Type objectType) [0x00116] in <795d7d5f77dc40f5bc8e819adb0a4748>:0
    5. Newtonsoft.Json.Serialization.DefaultContractResolver.CreateContract (System.Type objectType) [0x000e1] in <795d7d5f77dc40f5bc8e819adb0a4748>:0
    6.  Newtonsoft.Json.Serialization.DefaultContractResolver.ResolveContract (System.Type type) [0x00038] in <795d7d5f77dc40f5bc8e819adb0a4748>:0
    7. Newtonsoft.Json.Serialization.JsonSerializerInternalReader.GetContractSafe (System.Type type) [0x00005] in <795d7d5f77dc40f5bc8e81
    any ideas?

    EDIT: so it seems like an IL2CPP stripping issue. not sure if it is stripping the newtonsoft.json or my class, probably the latter. I have the newton from the asset store with the link.xml
     
    Last edited: Jan 18, 2020
  2. liortal

    liortal

    Joined:
    Oct 17, 2012
    Posts:
    3,455
    What is WP ? Its not clear what this class looks like.

    Also, are you deserializing the same way (e.g: exactly the same code) on mobile and in the editor) ?

    Lastly, can you show what the actual JSON you are deserializing looks like?
     
    Maplod and Joe-Censored like this.
  3. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    9,071
    It might be code stripping: if your code doesn't have an explicit constructor call for a WP class (i.e., somewhere that says
    new WP();
    ), then the constructor might get stripped. Look up code stripping and how to control it.
     
    Maplod and Joe-Censored like this.
  4. Maplod

    Maplod

    Joined:
    Jul 6, 2014
    Posts:
    6

    Thanks a lot! It was indeed a code stripping issue. disabling code stripping in the player settings solved the problem. thanks for pointing me in the right direction
     
    Kurt-Dekker likes this.
  5. Maplod

    Maplod

    Joined:
    Jul 6, 2014
    Posts:
    6
    so when I've moved from Mono to IL2CPP, disabling code stripping is not an option. tried to solve it but it seems like Im missing something more basic regarding reflections


    Code (CSharp):
    1.  
    2.  
    3. public class WP{
    4.  
    5.     public Acf acf {get; set;}
    6.     [JsonExtensionData]
    7.     public IDictionary<string, object> other {get; set;}
    8.  
    9. }
    10.  
    11. public class Acf
    12. {
    13.  
    14.     public string gesetz_Nr {get; set;}
    15.  
    16.     // law 1
    17.     public string gesetz_1 {get; set;}
    18.     public string gesetz_1_title {get; set;}
    19.     public string gesetz_1_source {get; set;}
    20.     public IDictionary<string, object> other  {get; set;}
    21. }
    22. public class Gesetz {
    23.  
    24.    public int number;
    25.     public string title;
    26.     public string source;
    27.  
    28. }
    29.  
    30. public class DataManager : MonoBehaviour {
    31.     public List<Gesetz> gesetzs = new List<Gesetz>();
    32.  
    33.     void Start () {
    34.      
    35.         StartCoroutine(GetText());
    36. }
    37.     IEnumerator GetText()
    38.     {
    39.  
    40.         string url = <URL>;
    41.         //string reply = new WebClient().DownloadString(url);
    42.         UnityWebRequest request = UnityWebRequest.Get(url);
    43.         yield return request.SendWebRequest();
    44.  
    45.         if (request.isNetworkError || request.isHttpError)
    46.         {
    47.             Debug.Log(request.error);
    48.         }
    49.         else
    50.         {
    51.        
    52.             yield return new WaitUntil(() => request.downloadHandler.isDone == true);
    53.  
    54.             Debug.Log(request.downloadHandler.text.Length);
    55.    
    56.  
    57.             string response = System.Text.Encoding.UTF8.GetString(request.downloadHandler.data);
    58.             Debug.Log(response);
    59.  
    60.             // dynamic data = JsonConvert.DeserializeObject<dynamic>(response);
    61.             //    Acf acf= JsonConvert.DeserializeObject<Acf>(response);
    62.              var appData = JsonConvert.DeserializeObject<List<WP>>(response);
    63.  
    64.                 Gesetz gesetz1 = new Gesetz();
    65.                 gesetz1.content = (appData[0].acf.gesetz_1).ToString();
    66.                 gesetz1.title = (appData[0].acf.gesetz_1_title).ToString();
    67.                 gesetz1.source = (appData[0].acf.gesetz_1_source).ToString();
    68.  
    69.                 gesetzs.Add(gesetz1);
    70. }
    71.         ES3.Save<List<Gesetz>>("allLaws",gesetzs);
    72. }

    what am I missing :) ?
     
    Last edited: Jan 10, 2020
  6. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    9,071
    Does the problem go away if you explicitly put a constructor call into your code, in a piece of code you are sure does not get stripped?
     
  7. Maplod

    Maplod

    Joined:
    Jul 6, 2014
    Posts:
    6
    doesnt go away. either I did it wrong or it didnt solve it
     
    Last edited: Jan 18, 2020
  8. Maplod

    Maplod

    Joined:
    Jul 6, 2014
    Posts:
    6
    anyone has an idea how to solve it?
     
  9. Arkade

    Arkade

    Joined:
    Oct 11, 2012
    Posts:
    621
    Hey, @Maplod
    You likely have to either add [Preserve] to a load of things or update a "link.xml" (in the project root directory).
    https://docs.unity3d.com/Manual/ManagedCodeStripping.html

    I've overcome several Json.Net issues with IL2CPP using this successfully. That said I've just started using [JsonExtensionData] the same as you and have run into the same problem (which led me here). I'll continue investigating but thought I'd post that so we're starting from the same place and can race each other to a solution (or you can post an update if you've solved it since your last post?) :)

    HTH
     
  10. Arkade

    Arkade

    Joined:
    Oct 11, 2012
    Posts:
    621
    Checking the JSON.Net source with the error, it's failing to construct a
    DefaultContractResolver.EnumerableDictionaryWrapper<TEnumeratorKey, TEnumeratorValue>
    .
    So merging the following into our link.xml files fixes its removal by the stripping process and fixes the problem:

    Code (XML):
    1.     <assembly fullname="Newtonsoft.Json">
    2.         <type fullname="Newtonsoft.Json.Serialization.DefaultContractResolver/EnumerableDictionaryWrapper`2" preserve="all" />
    3.     </assembly>
    N.b. I was mistaken about the "root directory" requirement for the link.xml -- they just need to be anywhere within Assets which does however mean they can't be in Packages (which is how I use Json.Net). HTH
     
unityunity