1

I'm getting some very weird behaviour in my Xamarin.Forms Project.

I'm retrieving some serialized data from a REST API. I'm then trying to use Json.NET to deserialize that to an object.

This works perfectly fine on Android and if I copy the code to a .NET console application it also works. However in my iOS project, the call to .DeserializeObject() just returns null. It doesn't throw an error or complain in any way.

I did find this discussion: https://forums.xamarin.com/discussion/15152/deserialization-not-working-with-json-net-on-ios-device-ios-simulator-works, but I didn't link all assemblies in the first place and trying to set the attribute suggested by T.J.Purtell.1752 didn't help either.

Could anyone tell me what to do here?

Thanks a lot!

Jan

EDIT

Here's a sample response of what I'm trying to deserialize:

[
   {
      "Isbn":{
         "Isbn10":"0099910101",
         "Isbn13":"9780099910107"
      },
      "Title":"A Farewell to Arms",
      "Authors":[
         "Ernest Hemingway"
      ],
      "Publisher":"Random House",
      "ReleaseDate":"1994",
      "PageCount":293,
      "Description":"In 1918 Ernest Hemingway went to war, to the 'war to end all wars'. He volunteered for ambulance service in Italy, was wounded and twice decorated. Out of his experiences came A Farewell to Arms. Hemingway's description of war is unforgettable. He recreates the fear, the comradeship, the courage of his young American volunteer and the men and women he meets in Italy with total conviction. But A Farewell to Arms is not only a novel of war. In it Hemingway has also created a love story of immense drama and uncompromising passion.",
      "ThumbnailUrl":"http://books.google.com/books/content?id=m68LhBiNv8YC&printsec=frontcover&img=1&zoom=1&source=gbs_api"
   },
   {
      "Isbn":{
         "Isbn10":"9044538780",
         "Isbn13":"9789044538786"
      },
      "Title":"Het huis van de namen",
      "Authors":[
         "Colm Tóibín"
      ],
      "Publisher":"Singel Uitgeverijen",
      "ReleaseDate":"2017-08-24",
      "PageCount":0,
      "Description":"Klytaimnestra heeft veel moeten doorstaan. Haar man heeft haar kind, haar mooie oudste dochter, geofferd aan de goden, en zij heeft hem niet kunnen tegenhouden. Hoe kan ze dit ooit te boven komen? En hoe zullen haar andere twee kinderen reageren op deze ontwrichtende gebeurtenis? Eén ding neemt ze zich voor: haar man zal dit met de dood moeten bekopen.",
      "ThumbnailUrl":"http://books.google.com/books/content?id=yl8yDwAAQBAJ&printsec=frontcover&img=1&zoom=1&edge=curl&source=gbs_api"
   }
]
dbc
  • 104,963
  • 20
  • 228
  • 340
japhwil
  • 299
  • 4
  • 16
  • Just to avoid confusion, do you have JSON library referenced in .iOS project? – foxanna Nov 19 '17 at 16:25
  • Yes I do. I also tried different versions, but since it doesn't seem to make any difference I'm currently using the latest stable one. – japhwil Nov 19 '17 at 16:37

6 Answers6

4

Just got back to this problem. In case anyone‘s wondering: Turns out the Xamarin Live Player I’ve recently had to use has some problems with Json.NET. (https://developer.xamarin.com/guides/cross-platform/live/limitations/)

I knew it had to be something stupid... Well maybe I can save someone else some time!

japhwil
  • 299
  • 4
  • 16
  • See also [this answer](https://stackoverflow.com/a/48246294/3744182) to [JsonConvert.SerializeObject always return {} in XamarinForms](https://stackoverflow.com/q/48041823/3744182) which states, *If you compile it to an APK it works fine on the actual device.* – dbc Oct 21 '18 at 14:19
2

Setting iOS Build Linker Behavior to "Link Framework SDKs only" fixed this for me.

As T.J.Purtell.1752 describes in the referenced xamarin thread, the Xamarin Linker will strip out unused types, methods, and fields.

Link Framework SDKs only prevents that happening for my application classes, which is fine in my conmtext.

Zef
  • 111
  • 1
  • 5
  • Thanks for the answer @zef! But as I said, the problem was just that I used the Xamarin Live Player and didn’t check its limitations regarding Json.NET. – japhwil Dec 02 '17 at 18:59
  • Sure, but the problem as stated also exists outside Live Player. This question and the link to the Xamarin thread helped me and would probably help others. – Zef Dec 02 '17 at 20:01
1

Based on the JSON being returned it would need to be desrialized to an array where the objects map for example

public class Isbn {
    public string Isbn10 { get; set; }
    public string Isbn13 { get; set; }
}

public class Item {
    public Isbn Isbn { get; set; }
    public string Title { get; set; }
    public IList<string> Authors { get; set; }
    public string Publisher { get; set; }
    public string ReleaseDate { get; set; }
    public int PageCount { get; set; }
    public string Description { get; set; }
    public string ThumbnailUrl { get; set; }
}

And then deserialized like

var items = JsonConvert.DeserializeObject<Item[]>(json);
Nkosi
  • 235,767
  • 35
  • 427
  • 472
  • That's exactly what I'm doing, only that I'm going straight to a List object: var books = JsonConvert.DeserializeObject>(response). And I mean it is working on Android and anywhere else so it has be some problem about iOS. – japhwil Nov 20 '17 at 05:40
  • Have you considered that perhaps iOS handles HTTP responses differently? might be worth doing a bit of googling around that. We use JsonConvert in our iOS application the exact same way you do, the only thing that could possibly be different is the way you handle those responses in iOS. – JoeTomks Nov 20 '17 at 09:01
  • @Digitalsa1nt Well I've thought about that. But when I debug the app running on my iPhone I see that the string response is OK. Could you maybe share the exact version of Json.NET and how you use the deserialization method so I could try that? – japhwil Nov 20 '17 at 11:28
  • Thanks a lot, this methode is better than using System.Convert.ToString – SOAL ABDELDJALLIL Apr 01 '20 at 00:36
1

Thanks a lot to all the responses so far! Sadly none of them worked for me.

After a lot of trial and error I found that I am able to access my data like so:

var blub = JsonConvert.DeserializeObject(booksString);
foreach (var element in (JArray)blub)
{
    var blublub = ((JObject)element).SelectToken("$.Title").ToString();
}

But it would be an absolute pain if I had to implement my whole API this way... Are there any other ideas from you guys?

japhwil
  • 299
  • 4
  • 16
0

Please try like this:

Item item = JObject.Parse (json).ToObject<Item> ();

Yes, it's kind of ugly fix, but if it's working, it's working :)

Taier
  • 2,109
  • 12
  • 22
  • Thanks for the hint! But now I'm getting an exception "Error reading JObject from JsonReader. Current JsonReader item is not an object" – japhwil Nov 19 '17 at 17:32
  • @japhwil could you please share a json that you receive? – Taier Nov 19 '17 at 17:37
0

Possible Causes

  1. The deserialized object does not have default constructor .. new Foo()
  2. The constructor contains complex objects such as ICommand, DelegateCommand.
  3. Some properties of the deserialized object is complex objects and consume computing power during serializing, deserializing.
  4. Is not selecting Link Frameword SDKs only
Jawad Sabir
  • 167
  • 2
  • 12