One can use custom converters by defining a class like this:
public class MyCustomConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(MyCustomType);
}
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)
{
var ret = new MyCustomType();
return ret;
}
}
And then using it like this:
MyCustomType item = JsonConvert.DeserializeObject<MyCustomType>(jsonString, new MyCustomTypeConverter());
My question is, how can I apply this deserializer when dealing with a list of MyCustomType
? Basically I have a Json array ([{ ... }, { ... }]
) and I would like to use the converter above on each item of the array to get a List<MyCustomType>
.
I know I can do it by hand using the JArray
object and its methods but I was wondering if there was an easier and cleaner way to do it.
Here's a simplified context.
C# (I want to deserialize a List
of those):
class MyCustomType
{
public Dictionary<string, string> Data
{
get;
set;
}
public int Id
{
get;
set;
}
}
JSON (one item in the array sample):
{
"Id": 50,
"Data": [
"Hello",
"World"
]
}
C# Deserialization I want to apply:
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var ret = new MyCustomType();
ret.Data = new Dictionary<string, string>();
while (reader.Read())
{
if (reader.TokenType == JsonToken.EndObject)
{
continue;
}
var value = reader.Value.ToString();
switch(value)
{
case "Id":
ret.Id = reader.ReadAsInt32().Value;
break;
case "Data":
ret.Data.Add(MySingleton.Instance.CurrentLanguage, reader.ReadAsString());
break;
}
}
return ret;
}
While L.B's answer works, there are cases where a converter is indeed necessary - for instance, when you don't ever get to touch the raw JSON and only get to attribute ASP.NET methods that will be accessible to HTTP requests.
In that case, you can use the JsonPropertyAttribute
class and assign a value to its ItemConverterType
property:
[JsonProperty(ItemConverterType = typeof(MyCustomConverter))]
public List<MyCustomType> Items { get; set; }
var obj = JsonConvert.DeserializeObject<MyCustomType>(json);
if your json is an array then use
var obj = JsonConvert.DeserializeObject<List<MyCustomType>>(json);
And if you can change the type of Data
to List<string>
, you don't even need jsonConverter
public class MyCustomType
{
public int Id { get; set; }
[JsonConverter(typeof(MyCustomConverter))]
public Dictionary<string, string> Data { get; set; }
}
public class MyCustomConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(MyCustomType);
}
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)
{
// read the string array and convert it to dictionary
// as declared in your MyCustomType
var arr = serializer.Deserialize<List<string>>(reader);
return arr.ToDictionary(x => x, x => x);
}
}
Just deserialize as
var yourObj = JsonConvert.DeserializeObject<MyCustomType.Rootobject>(yourjson);
public class MyCustomType
{
public class Rootobject
{
public Datum[] data { get; set; }
}
public class Datum
{
public string id { get; set; }
public string al { get; set; }
public string[] datapsi { get; set; }
public string[] tags { get; set; }
public string partype { get; set; }
public Info info { get; set; }
public Factors factors { get; set; }
public Espace[] espace { get; set; }
public Annex Annex { get; set; }
}
public class Info
{
public string nopub { get; set; }
public int nodem { get; set; }
}
public class Factors
{
public int a { get; set; }
public float b { get; set; }
public int c { get; set; }
public float d { get; set; }
public int e { get; set; }
public float f { get; set; }
public float g { get; set; }
public int h { get; set; }
public int i { get; set; }
public int j { get; set; }
public int k { get; set; }
public int l { get; set; }
public float m { get; set; }
public int n { get; set; }
public int o { get; set; }
public int p { get; set; }
public float q { get; set; }
public float r { get; set; }
public int s { get; set; }
public float t { get; set; }
}
public class Annex
{
public string name { get; set; }
public Image image { get; set; }
}
public class Espace
{
public string id { get; set; }
public string description { get; set; }
public Datatip datatip { get; set; }
public Image image { get; set; }
public string resource { get; set; }
public int delta { get; set; }
public int[] target { get; set; }
public string targetType { get; set; }
public string targetOneLined { get; set; }
public int[] alx { get; set; }
public string alxOneLined { get; set; }
public int[][] damps { get; set; }
public string[] dampsOneLined { get; set; }
public Var[] vars { get; set; }
public object misc { get; set; }
public string miscOneLined { get; set; }
}
public class Datatip
{
public string[] label { get; set; }
public string[] damps { get; set; }
}
public class Image
{
public string full { get; set; }
public string sprite { get; set; }
public string group { get; set; }
public int x { get; set; }
public int y { get; set; }
public int w { get; set; }
public int h { get; set; }
}
public class Var
{
public string key { get; set; }
public string link { get; set; }
public float coeff { get; set; }
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With