C# 如何在反序列化时丢弃具有特定值的JSON元素

C# 如何在反序列化时丢弃具有特定值的JSON元素,c#,json.net,C#,Json.net,这是一个有趣的情况。我的应用程序保存并加载来自MongoDB的JSON数据,MongoDB 95%的时间运行良好。这种情况下的JSON数据如下所示: { "isDemo": true, "CustomerReference": "nabTest", "Fee": null, "OrderId": "48/XYZ3", "A

这是一个有趣的情况。我的应用程序保存并加载来自MongoDB的JSON数据,MongoDB 95%的时间运行良好。这种情况下的JSON数据如下所示:

{
    "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
使用一些简单的字符串来键入{Bool,Double}解析器:

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的人来说,这仍然是一个很好的答案。