反序列化不一致 JSON 属性
Deserialize inconsistent JSON property
希望有人可以帮助我解决我试图使用 Newtonsoft.Json.
反序列化的大型 JSON 文件中发生的以下不一致问题
对象的其中一个属性偶尔会显示为:
"roles": [
{
"field1" : "value",
"field2" : "value"
}
]
而其他时候 属性 显示为:
"roles": {
"roles": [
{
"field1" : "value",
"field2" : "value"
}
]
}
供参考,此属性在其class中实现为:
[JsonProperty("roles")]
public List<Role> Roles { get; set; }
我需要发生的是,每当上述第二种情况发生时,对象内容像第一种情况一样被反序列化。即“外部”对象是 discarded/ignored
当单独的 属性 有时作为对象出现,有时作为数组出现时,我设法处理了此文件中的另一个不一致,在其 class 定义中使用以下方法:
[JsonConverter(typeof(SingleValueArrayConverter<Address>))]
public List<Address> Location { get; set; }
并实现为:
public class SingleValueArrayConverter<T> : 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)
{
object retVal = new Object();
if (reader.TokenType == JsonToken.StartObject)
{
T instance = (T)serializer.Deserialize(reader, typeof(T));
retVal = new List<T>() { instance };
}
else if (reader.TokenType == JsonToken.StartArray)
{
retVal = serializer.Deserialize(reader, objectType);
}
return retVal;
}
public override bool CanConvert(Type objectType)
{
return true;
}
}
但是,我无法解决这个问题。
有人可以帮忙吗?
最简单的方法(不一定是最干净的)是在反序列化之前手动更改字符串 -
jsonString = jsonString.replace("\"roles\": {", "\"rolesContainer\": {");
jsonString = jsonString.replace("\"roles\":{", "\"rolesContainer\": {");
然后在您的主代码中,您会将 rolesContainer 和 roles 作为字段 - 然后在
之后合并它们
public List<Role> roles { get; set; }
public RoleContainer rolesContainer { get; set; }
public class RoleContainer {
Public List<Role> roles;
}
有点脏,但应该可以用
您也可以使用 JsonConverter
处理这种不一致。它会与您拥有的略有不同,但想法非常相似:
public class ArrayOrWrappedArrayConverter<T> : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return typeof(List<T>).IsAssignableFrom(objectType);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JToken token = JToken.Load(reader);
if (token.Type == JTokenType.Array)
{
return CreateListFromJArray((JArray)token, serializer);
}
if (token.Type == JTokenType.Object)
{
JObject wrapper = (JObject)token;
JProperty prop = wrapper.Properties().FirstOrDefault();
if (prop.Value.Type == JTokenType.Array)
{
return CreateListFromJArray((JArray)prop.Value, serializer);
}
}
// If the JSON is not what we expect, just return an empty list.
// (Could return null or throw an exception here instead if desired.)
return new List<T>();
}
private List<T> CreateListFromJArray(JArray array, JsonSerializer serializer)
{
List<T> list = new List<T>();
serializer.Populate(array.CreateReader(), list);
return list;
}
public override bool CanWrite => false;
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
然后只需将转换器添加到您的 Roles
属性 就可以了:
[JsonProperty("roles")]
[JsonConverter(typeof(ArrayOrWrappedArrayConverter<Role>))]
public List<Role> Roles { get; set; }
希望有人可以帮助我解决我试图使用 Newtonsoft.Json.
反序列化的大型 JSON 文件中发生的以下不一致问题对象的其中一个属性偶尔会显示为:
"roles": [
{
"field1" : "value",
"field2" : "value"
}
]
而其他时候 属性 显示为:
"roles": {
"roles": [
{
"field1" : "value",
"field2" : "value"
}
]
}
供参考,此属性在其class中实现为:
[JsonProperty("roles")]
public List<Role> Roles { get; set; }
我需要发生的是,每当上述第二种情况发生时,对象内容像第一种情况一样被反序列化。即“外部”对象是 discarded/ignored
当单独的 属性 有时作为对象出现,有时作为数组出现时,我设法处理了此文件中的另一个不一致,在其 class 定义中使用以下方法:
[JsonConverter(typeof(SingleValueArrayConverter<Address>))]
public List<Address> Location { get; set; }
并实现为:
public class SingleValueArrayConverter<T> : 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)
{
object retVal = new Object();
if (reader.TokenType == JsonToken.StartObject)
{
T instance = (T)serializer.Deserialize(reader, typeof(T));
retVal = new List<T>() { instance };
}
else if (reader.TokenType == JsonToken.StartArray)
{
retVal = serializer.Deserialize(reader, objectType);
}
return retVal;
}
public override bool CanConvert(Type objectType)
{
return true;
}
}
但是,我无法解决这个问题。 有人可以帮忙吗?
最简单的方法(不一定是最干净的)是在反序列化之前手动更改字符串 -
jsonString = jsonString.replace("\"roles\": {", "\"rolesContainer\": {");
jsonString = jsonString.replace("\"roles\":{", "\"rolesContainer\": {");
然后在您的主代码中,您会将 rolesContainer 和 roles 作为字段 - 然后在
之后合并它们public List<Role> roles { get; set; }
public RoleContainer rolesContainer { get; set; }
public class RoleContainer {
Public List<Role> roles;
}
有点脏,但应该可以用
您也可以使用 JsonConverter
处理这种不一致。它会与您拥有的略有不同,但想法非常相似:
public class ArrayOrWrappedArrayConverter<T> : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return typeof(List<T>).IsAssignableFrom(objectType);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JToken token = JToken.Load(reader);
if (token.Type == JTokenType.Array)
{
return CreateListFromJArray((JArray)token, serializer);
}
if (token.Type == JTokenType.Object)
{
JObject wrapper = (JObject)token;
JProperty prop = wrapper.Properties().FirstOrDefault();
if (prop.Value.Type == JTokenType.Array)
{
return CreateListFromJArray((JArray)prop.Value, serializer);
}
}
// If the JSON is not what we expect, just return an empty list.
// (Could return null or throw an exception here instead if desired.)
return new List<T>();
}
private List<T> CreateListFromJArray(JArray array, JsonSerializer serializer)
{
List<T> list = new List<T>();
serializer.Populate(array.CreateReader(), list);
return list;
}
public override bool CanWrite => false;
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
然后只需将转换器添加到您的 Roles
属性 就可以了:
[JsonProperty("roles")]
[JsonConverter(typeof(ArrayOrWrappedArrayConverter<Role>))]
public List<Role> Roles { get; set; }