I've been having trouble finding a question about my particular case:
I need to deserialize the following JSON:
{
"name": "My Farm",
"barns": [
{
"name"": "Barn A"",
"animalTypes": [
"Cow",
"Goat"
]
}
]
}
to the following code model:
public class Farm
{
public string name;
public Barn[] barns;
}
public class Barn
{
public string name;
public AnimalType[] animalTypes;
}
public class AnimalType
{
public int typeID;
}
The problem: I need to deserialize a JSON string (which described an animal species name) into an 'AnimalType' object which contains a "type ID" int. This requirement is not something I can change.
To get the animal's integer type ID, I have access to an externally supplied "AnimalTypeResolver" class, which looks like this:
public class AnimalTypeResolver
{
public int GetAnimalType(string animalTypeName)
{
// queries a map to return the right ID.
}
}
I can query that resolver to get the int value I need to store for each animal type.
So, I tried to write a custom JSONConverter for AnimalType:
public class AnimalTypeConverter : JsonConverter<AnimalType>
{
public AnimalTypeResolver animalTypeResolver;
public AnimalTypeConverter(AnimalTypeResolver animalTypeResolver)
{
this.animalTypeResolver = animalTypeResolver;
}
public override bool CanWrite => false;
public override AnimalType ReadJson(ref JsonReader reader, Type objectType, AnimalType existingValue, bool hasExistingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.String)
{
string animalTypeName = (string)reader.Value;
return new AnimalType
{
typeID = animalTypeResolver.GetAnimalType(animalTypeName)
};
}
return null;
}
public override void WriteJson(JsonWriter writer, AnimalType value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
And my deserialization code looks like this:
string farmJSON =
@"{
""name"": ""My Farm"",
""barns"": [
{
""name"": ""Barn A"",
""animalTypes"": [
""Cow"",
""Goat""
]
}
]
}";
JsonSerializer serializer = new JsonSerializer();
serializer.Converters.Add(new AnimalTypeConverter(animalTypeResolver)); // this animalTypeResolver is supplied from elsewhere in code.
Farm farm = JsonConvert.DeserializeObject<Farm>(farmJSON);
But I get a runtime error:
ArgumentException: Could not cast or convert from System.String to AnimalType.
From reading similar questions, I believe my problem is that I'm trying to deserialize a nested field of a custom type (AnimalType[]). Other answers have explained that JToken.FromObject() creates a new JsonSerializer for each level of deserialization, which has no concept of the JsonConverters I added to a higher-level serializer.
However, For one reason or another, the other questions on this site have answers which aren't exactly applicable to my case.
How I can use my custom JsonConverter, to handle a case in which the data is deeply nested?
If anyone can offer advice about how to make this work, thank you!
JsonConvert.DeserializeObject<Farm>(farmJSON)
does not use your JsonSerializer instance. I mean, how could it possibly access the serializer variable that you created and assigned in your code?
You have two choices: Either use the Deserialize method of the serializer instance you did just setup to deserialize your json data and not use JsonConvert.DeserializeObject.
Or instead of setting up a serializer, define some JsonSerializerSettings with your custom JsonConverter and pass those settings to the JsonConvert.DeserializeObject method . Alternatively you could instead also define default serialization settings for JsonConvert.DeserializeObject as demonstrated here in the Newtonsoft.Json documentation: https://www.newtonsoft.com/json/help/html/DefaultSettings.htm
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.