Deserialize an array in an array

I just downloaded a huge JSON file with all the current MTG sets / maps , and I want to deserialize it all.

I got most of each deserialized set, but I got confused in trying to deserialize the booster object in each set:

enter image description here

enter image description here

As you can see from the above two images, each booster object has a list of lines, but for some booster objects there is also an additional array of more lines. Removing the deserialization of an array of strings exclusively is not a problem. My problem arises when I start those instances where there is an array of strings in the booster object that requires deserialization.

Currently, the property that I configured to handle this deserialization is:

 public IEnumerable<string> booster { get; set; } 

But when I come across those cases where there is another array inside the booster , I get an exception where Newtonsoft.Json complains that it does not know how to handle deserialization.

So, the question then becomes: how can I deserialize an array of strings contained in an array of strings? And what kind of object should look like in C # code to handle deserialization?

+5
source share
4 answers

You can deserialize an element as string[] , even assuming that the element will not be a collection. So, create your own serializer;

 public class StringArrayConverter : JsonConverter { public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { throw new NotImplementedException(); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { JArray array = JArray.Load(reader); for (int i = 0; i < array.Count; i++) { //If item is just a string, convert it string collection if (array[i].Type == JTokenType.String) { array[i] = JToken.FromObject(new List<string> {array[i].ToObject<string>()}); } } return array.ToObject<List<string[]>>(); } public override bool CanConvert(Type objectType) { return (objectType == typeof(List<string[]>)); } } public class JsonObject { [JsonConverter(typeof(StringArrayConverter))] public List<string[]> booster { get; set; } } 

Then deserialize json;

 var data = JsonConvert.DeserializeObject<JsonObject>(json); 

Finally, you can deserialize json, as I said below;

 { "booster": [ "1", "2", ["3","4"] ] } 
+1
source

If you use C # as a programming language, use the link below to generate a C # class from a JSON string

http://json2csharp.com/

Then you can use the generated class in your code to deserialize your json string for the object using JsonConvert.DeserializeObject (jssonstring)

0
source

The easiest solution is to change the type to IEnumerable<object> . That way, it can store string or string[] .

Or you can create an Item class with two properties of the string and string[] types. Then you can create another property that returns a value that is not null, so now instead of the whole element being an object , you can have a special class that returns only one of two types, so you can be sure that you get either string or string[] . Hope this makes sense.

Your Property: public IEnumerable<Item> booster { get; set; } public IEnumerable<Item> booster { get; set; }

 public class Item { private string _text; private string[] _array; public object Value => (object)_text ?? (object)_array; public Item(string text) { _text = text; } public Item(string[] array) { _array = array; } } 

When you need to use this value, you can check if it is a string or a string [] as follows:

 if(myItem is string text) { // operate on variable text } else // you can be sure that myItem is of type string[] because we covered this up in the Item class { var array = (string[])myItem; // operate on variable array } 
0
source

Another option would be to simulate a β€œbooster” as an IEnumerable<string[]> , and then use a custom JsonConverter to force the transfer of strings to arrays. In the process of testing this theory, I wrote a (minimally tested, but functional) converter for you :)

 public class ForceStringToArrayConverter : JsonConverter { public override bool CanConvert(Type objectType) { return (objectType == typeof(IEnumerable<string[]>)); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { var listObject = new List<string[]>(); var jObject = JToken.Load(reader); foreach (JToken token in jObject.Children()) { if (token.Type == JTokenType.Array) { var arrayObj = (JArray)token; listObject.Add(arrayObj.ToObject<string[]>()); } else if (token.Type == JTokenType.String) { listObject.Add(new string[] { token.ToString() }); } } return listObject; } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { throw new NotImplementedException(); } } 

Then, when you call DeserializeObject, pass it your own converter:

  var obj = Newtonsoft.Json.JsonConvert.DeserializeObject<YourTypeHere>(testJson, new ForceStringToArrayConverter() ); 
0
source

Source: https://habr.com/ru/post/1274823/


All Articles