JSON.Net - 如何反序列化自定义类型的嵌套字段
JSON.Net - How to deserialize a nested field of a custom type
我一直无法找到关于我的特定案例的问题:
我需要反序列化以下 JSON:
{
"name": "My Farm",
"barns": [
{
"name"": "Barn A"",
"animalTypes": [
"Cow",
"Goat"
]
}
]
}
到以下代码模型:
public class Farm
{
public string name;
public Barn[] barns;
}
public class Barn
{
public string name;
public AnimalType[] animalTypes;
}
public class AnimalType
{
public int typeID;
}
问题:我需要将 JSON 字符串(描述动物物种名称)反序列化为包含“类型 ID”int 的 'AnimalType' 对象。这个要求不是我能改变的。
为了获取动物的整数类型 ID,我可以访问外部提供的“AnimalTypeResolver”class,它看起来像这样:
public class AnimalTypeResolver
{
public int GetAnimalType(string animalTypeName)
{
// queries a map to return the right ID.
}
}
我可以查询该解析器以获得我需要为每种动物类型存储的 int 值。
因此,我尝试为 AnimalType 编写自定义 JSON转换器:
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();
}
}
我的反序列化代码如下所示:
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);
但是我遇到运行时错误:
ArgumentException: Could not cast or convert from System.String to AnimalType.
通过阅读类似的问题,我相信我的问题是我正在尝试反序列化自定义类型 (AnimalType[]) 的嵌套字段。其他答案解释说 JToken.FromObject() 为每个反序列化级别创建一个新的 JsonSerializer,它没有我添加到更高级别序列化程序的 JsonConverters 的概念。
但是,出于某种原因,本网站上其他问题的答案并不完全适用于我的情况。
如何使用我的自定义 JsonConverter 来处理数据深度嵌套的情况?
如果有人可以提供有关如何进行此工作的建议,谢谢!
JsonConvert.DeserializeObject<Farm>(farmJSON)
不使用您的 JsonSerializer 实例。我的意思是,它怎么可能访问您在代码中创建和分配的 serializer 变量?
您有两个选择:要么使用您刚刚设置的 Deserialize method of the serializer 实例来反序列化您的 json 数据,要么不 使用 JsonConvert.DeserializeObject .
或者不设置序列化器,而是定义一些 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
我一直无法找到关于我的特定案例的问题:
我需要反序列化以下 JSON:
{
"name": "My Farm",
"barns": [
{
"name"": "Barn A"",
"animalTypes": [
"Cow",
"Goat"
]
}
]
}
到以下代码模型:
public class Farm
{
public string name;
public Barn[] barns;
}
public class Barn
{
public string name;
public AnimalType[] animalTypes;
}
public class AnimalType
{
public int typeID;
}
问题:我需要将 JSON 字符串(描述动物物种名称)反序列化为包含“类型 ID”int 的 'AnimalType' 对象。这个要求不是我能改变的。
为了获取动物的整数类型 ID,我可以访问外部提供的“AnimalTypeResolver”class,它看起来像这样:
public class AnimalTypeResolver
{
public int GetAnimalType(string animalTypeName)
{
// queries a map to return the right ID.
}
}
我可以查询该解析器以获得我需要为每种动物类型存储的 int 值。
因此,我尝试为 AnimalType 编写自定义 JSON转换器:
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();
}
}
我的反序列化代码如下所示:
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);
但是我遇到运行时错误:
ArgumentException: Could not cast or convert from System.String to AnimalType.
通过阅读类似的问题,我相信我的问题是我正在尝试反序列化自定义类型 (AnimalType[]) 的嵌套字段。其他答案解释说 JToken.FromObject() 为每个反序列化级别创建一个新的 JsonSerializer,它没有我添加到更高级别序列化程序的 JsonConverters 的概念。
但是,出于某种原因,本网站上其他问题的答案并不完全适用于我的情况。
如何使用我的自定义 JsonConverter 来处理数据深度嵌套的情况?
如果有人可以提供有关如何进行此工作的建议,谢谢!
JsonConvert.DeserializeObject<Farm>(farmJSON)
不使用您的 JsonSerializer 实例。我的意思是,它怎么可能访问您在代码中创建和分配的 serializer 变量?
您有两个选择:要么使用您刚刚设置的 Deserialize method of the serializer 实例来反序列化您的 json 数据,要么不 使用 JsonConvert.DeserializeObject .
或者不设置序列化器,而是定义一些 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