C# 如何在反序列化时丢弃具有特定值的JSON元素
这是一个有趣的情况。我的应用程序保存并加载来自MongoDB的JSON数据,MongoDB 95%的时间运行良好。这种情况下的JSON数据如下所示:C# 如何在反序列化时丢弃具有特定值的JSON元素,c#,json.net,C#,Json.net,这是一个有趣的情况。我的应用程序保存并加载来自MongoDB的JSON数据,MongoDB 95%的时间运行良好。这种情况下的JSON数据如下所示: { "isDemo": true, "CustomerReference": "nabTest", "Fee": null, "OrderId": "48/XYZ3", "A
{
"isDemo": true,
"CustomerReference": "nabTest",
"Fee": null,
"OrderId": "48/XYZ3",
"Asynchronous": false,
}
// 'result' is of type object, loaded from MongoDB
var resultStr = JsonConvert.SerializeObject(result);
var obj = JsonConvert.DeserializeObject<T>(resultStr, jsonSerializerSettings);
剩下的5%时间,遗留应用程序加载一些XML数据,将其转换为JSON格式,并将其插入同一个MongoDB集合。这种情况下的JSON数据如下所示:
{
"@xmlns:xsi":"http://www.w3.org/2001/XMLSchema-instance",
"@xmlns:xsd":"http://www.w3.org/2001/XMLSchema",
"@xmlns":"http://MyDomain.com.au/SomeService.Contract/2007/06/18",
"isDemo":{
"@xmlns":"http://MyDomain.com.au/ABC.Services",
"#text":"true"
},
"Asynchronous":{
"@xmlns":"http://MyDomain.com.au/ABC.Services"
"#text":"false"
},
"Fee":{
"@xsi:nil":"true",
"@xmlns":"http://MyDomain.com.au/ABC.Services"
},
"CustomerReference":{
"@xmlns":"http://MyDomain.com.au/ABC.Services"
},
"OrderId":"48/XYZ3"
}
在这种情况下,Newtonsoft反序列化程序会崩溃,但出现以下异常:
Newtonsoft.Json.JsonReaderException:'遇到意外字符
分析值时:{.Path'CustomerReference',第1行,位置
919。”
最低代码如下所示:
{
"isDemo": true,
"CustomerReference": "nabTest",
"Fee": null,
"OrderId": "48/XYZ3",
"Asynchronous": false,
}
// 'result' is of type object, loaded from MongoDB
var resultStr = JsonConvert.SerializeObject(result);
var obj = JsonConvert.DeserializeObject<T>(resultStr, jsonSerializerSettings);
/“result”是从MongoDB加载的object类型
var resultStr=JsonConvert.SerializeObject(结果);
var obj=JsonConvert.DeserializeObject(resultStr,jsonSerializerSettings);
处理这种情况的优雅方式是什么,代码更改最少。请在模型中使用如下方式:
公共类用户
{
//始终需要字符串值
[JsonProperty(“name”,Required=Required.Always)]
公共字符串名称{get;set;}
//不需要任何值
[JsonProperty(“角色”,NullValueHandling=NullValueHandling.Ignore)]
公共字符串角色{get;set;}
//属性被忽略
[JsonIgnore]
公共字符串密码{get;set;}
}
使用Json.NET序列化属性生成的结果:
{
“类型”:“对象”,
“财产”:{
“姓名”:{
“类型”:“字符串”
},
“作用”:{
“类型”:[
“字符串”,
“空”
]
}
},
“必需”:[
“姓名”
]
}
普通Json的对象表示应该如下所示:
using J = Newtonsoft.Json.JsonPropertyAttribute;
public partial class Data
{
[J("isDemo")] public bool? IsDemo { get; set; }
[J("Asynchronous")] public bool? IsAsynchronous { get; set; }
[J("OrderId")] public string OrderId { get; set; }
[J("CustomerReference")] public string CustomerReference { get; set; }
[J("Fee")] public double? Fee { get; set; }
}
虽然有一个自定义的处理方式,但整个Xml表示形式将很好。我发现很难编写和维护。你应该分而治之:
- 生成一个表示Xml ish Json的类
- 删除不必要的属性,必要时保留Xml“nil”
- 创建简单的自定义转换器,将字符串表示形式映射到正确的类型。 例如:“true”=>bool,“123”=>int
internal class BoolParseStringConverter : JsonConverter
{
public override bool CanConvert(Type t) => t == typeof(bool) || t == typeof(bool?);
public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null) return null;
var value = serializer.Deserialize<string>(reader);
if (Boolean.TryParse(value, out bool b))
{
return b;
}
throw new Exception("Cannot unmarshal type bool");
}
public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer)
{
if (untypedValue == null)
{
serializer.Serialize(writer, null);
return;
}
var value = (bool)untypedValue;
var boolString = value ? "true" : "false";
serializer.Serialize(writer, boolString);
return;
}
public static readonly BoolParseStringConverter Singleton = new BoolParseStringConverter();
}
internal class DoubleParseStringConverter : JsonConverter
{
public override bool CanConvert(Type t) => t == typeof(double) || t == typeof(double?);
public override object ReadJson(JsonReader reader, Type t, object existingValue, JsonSerializer serializer)
{
if (reader.TokenType == JsonToken.Null) return null;
var value = serializer.Deserialize<string>(reader);
if (Double.TryParse(value, out double l))
{
return l;
}
throw new Exception("Cannot unmarshal type long");
}
public override void WriteJson(JsonWriter writer, object untypedValue, JsonSerializer serializer)
{
if (untypedValue == null)
{
serializer.Serialize(writer, null);
return;
}
var value = (double)untypedValue;
serializer.Serialize(writer, value.ToString());
return;
}
public static readonly DoubleParseStringConverter Singleton = new DoubleParseStringConverter();
}
为了知道它是普通的Json还是Xml格式的Json,我将使用try-catch。
这样,我就不必编写complexe
JsonConverter
或同时表示普通和Xml格式的类。最优雅的处理方法是确保没有将所有Xml名称空间都放入json中,如果做不到这一点,则可能需要编写转换器并过滤掉json中的所有Gunkone告诉我们类型是什么e是费用。你介意给出第一个Json的对象表示形式吗。@CodeCaster,在写这篇文章之前,我看过并测试了你提出的解决方案。阅读文档,它应该可以正常工作。但我天真的尝试失败了。所以我想,如果它因为任何原因都不是有效的Xml,该怎么办。我想到了这个。但我没有玩使用“`反序列化XMLNode
进行mutch,无法判断Xml是坏的还是坏的。我知道这是大量代码,可以看作是复杂的。例如,所有转换器都可以删除,我们将所有内容映射到字符串,只在ToDataType()中将其转换
@CodeCaster,我认为对于任何将真正的Xml作为Json的人来说,这仍然是一个很好的答案。