gpt4 book ai didi

json - NewtonSoft JsonConvert - 反序列化一个看起来像 { “@nil” : “true” } 的 JSON 对象

转载 作者:行者123 更新时间:2023-12-02 17:18:09 24 4
gpt4 key购买 nike

我正在尝试反序列化休息服务返回的以下 JSON:

[{
"Vehicle": {
"Id": "1",
"RenewalDate": {
"@nil": "true"
}
}}]

该服务似乎将 XML 转换为 JSON,因此 XML nil 作为 JSON 字符串的一部分包含在内。

请告诉我如何在 Newtonsoft 反序列化方法中处理此问题?

如果更新日期包含在字符串中,反序列化工作正常。

最佳答案

在没有 Minimal, Complete, and Verifiable example 的情况下关于您的问题,我假设您正在尝试反序列化为如下所示的类列表:

public class Vehicle
{
public string Id { get; set; }

[XmlElement(IsNullable = true)]
public DateTime? RenewalDate { get; set; }
}

public class RootObject
{
public Vehicle Vehicle { get; set; }
}

并且,属性 "RenewalDate" 的反序列化失败,因为 JSON 中出现的不是 null 值,而是一个包含已翻译的 xsi:nil="true" 的对象。属性存在。

解决这个问题的一种方法是引入以下 custom JsonConverter :

public class NullableStructConverter<T> : JsonConverter where T : struct
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(Nullable<T>);
}

public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var underlyingType = Nullable.GetUnderlyingType(objectType);
if (underlyingType == null)
throw new InvalidOperationException(string.Format("Type {0} is not nullable", objectType));
var token = JToken.Load(reader);
if (token.Type == JTokenType.Null)
return null;
if (token.WasNilXmlElement())
return null;
return token.ToObject(underlyingType, serializer);
}

public override bool CanWrite { get { return false; } }

public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}

public static partial class JTokenExtensions
{
public static bool WasNilXmlElement(this JToken token)
{
if (token == null)
return true;
if (token.Type == JTokenType.Null)
return true;
var obj = token as JObject;
if (obj != null)
{
// Check if all properties were translated from XML attributes
// and one was translated from xsi:nil = true
// There might be namespaces present as well, e.g.
// "@xmlns:p3": "http://www.w3.org/2001/XMLSchema-instance"
if (obj.Properties().All(p => p.Name.StartsWith("@"))
&& obj.Properties().Any(p => p.Name == "@nil" || p.Name.EndsWith(":nil") && p.Value.ToString() == "true"))
return true;
}
return false;
}
}

然后反序列化如下:

var settings = new JsonSerializerSettings 
{
Converters = { new NullableStructConverter<DateTime>() }
// Whatever other settings you require.
};
var root = JsonConvert.DeserializeObject<RootObject[]>(json, settings);

工作 .Net fiddle .

另一种选择是将 JSON 加载到 JToken 中层次结构,用 null JSON 值替换从 nil XML 元素翻译的所有 JSON 对象,然后最后反序列化到您的模型。首先,介绍以下使用第一个解决方案中的 WasNilXmlElement() 的扩展方法:

public static partial class JTokenExtensions
{
public static JToken ReplaceNilXmlElementObjectsWithNull(this JToken root)
{
var rootContainer = root as JContainer;
if (rootContainer == null)
return root;
var list = rootContainer.DescendantsAndSelf()
.OfType<JObject>()
.Where(o => o.WasNilXmlElement())
.ToList();
foreach (var obj in list)
{
var replacement = JValue.CreateNull();
if (obj.Parent != null)
obj.Replace(replacement);
if (root == obj)
root = replacement;
}
return root;
}
}

反序列化如下:

var settings = new JsonSerializerSettings
{
// Whatever settings you require.
};
var root = JsonConvert.DeserializeObject<JToken>(json, settings)
.ReplaceNilXmlElementObjectsWithNull()
.ToObject<RootObject[]>(JsonSerializer.CreateDefault(settings));

此解决方案避免了为每个可空类型使用 JsonConverter 的需要。工作 fiddle #2 .

关于json - NewtonSoft JsonConvert - 反序列化一个看起来像 { “@nil” : “true” } 的 JSON 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45117277/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com