【问题标题】:Json.Net Deserializing "NA" for Numeric ValuesJson.Net 为数值反序列化“NA”
【发布时间】:2016-05-02 06:23:18
【问题描述】:

我正在尝试使用 Json.Net 反序列化数字数据,其中如果缺少值可能会被指定为“NA”,例如

{
    "readings": [
        { "temperature" : 75 } ,
        { "temperature" : "NA" }
    ]
}

我想将值解析为 double? 类型,例如

public class Reading
{
    public double? Temperature { get; set; }
}

我的示例中的第一个读数(净效应)是“75”,第二个读数是“null”。

我无法控制提供给我的 JSON。

JsonConverter 是让 Json.Net 为我处理此问题的唯一方法,还是有更简单的方法? (我总是可以为 Json 反序列化值创建一个私有类变量,然后将我自己的公共属性添加到私有值中,它可以做任何我想做的事情,但是由于我有很多属性要处理,所以需要很多额外的代码.)

【问题讨论】:

  • 可以使用 NewtonSoft 的 Json 库。

标签: c# json json.net deserialization numeric


【解决方案1】:

我建议构建一个自定义类型转换器,但如果您真的不想这样做,您可以implement an error handler 忽略反序列化异常。假设您有这样的设置:

public class Reading
{
    public double? Temperature { get; set; }
}

public class Root
{
    public List<Reading> Readings { get; set; }
}

你可以这样写:

Root obj = JsonConvert.DeserializeObject<Root>(
    json, new JsonSerializerSettings
    {
        Error = (sender, args) =>
        {
            Reading reading = args.CurrentObject as Reading;

            if (reading != null && args.ErrorContext.Member.ToString() == "temperature")
            {
                reading.Temperature = null;
                args.ErrorContext.Handled = true;
            }
        }
    });

这里我们正在处理Error 事件,如果我们在反序列化temperature 成员时检测到错误,则将错误标记为已处理。

以防万一您想使用自定义转换器,如下所示:

public class NAConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(Reading);
    }

    public override object ReadJson(
        JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JObject obj = JObject.Load(reader);

        Reading reading = new Reading();
        string tempStr = obj.Value<string>("temperature");

        double temp;

        if (Double.TryParse(tempStr, out temp))
        {
            reading.Temperature = temp;
        }

        return reading;
    }

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

【讨论】:

  • 我在 Json.Net 文档中遇到了这个问题。似乎可以基于每个属性指定转换器:

    // new Date(976918263055) [JsonProperty] [JsonConverter(typeof(JavaScriptDateTimeConverter))] public DateTime LastModified { get;放; }
  • (啊。抱歉格式错误——没有仔细阅读帮助。)
  • @BoCoKeith:是的!这绝对是一个选择。随心所欲。
【解决方案2】:

在您的服务器代码中,将温度设为模型中的字符串,然后使用TryParse 查看是否可以将其转换为双精度。

double tempValue;

if (Double.TryParse(yourObject.Temperature, out temp)){
  // successfully parsed to a double
  // do whatever you're going to do with the value
}
else {
  // couldn't be parsed as a double, handle accordingly
}

https://msdn.microsoft.com/en-us/library/994c0zb1(v=vs.110).aspx

【讨论】:

    【解决方案3】:

    我认为没有办法让反序列化器将字符串转换为可为空的双精度。最好将值反序列化为字符串,然后在使用时将字符串转换为数值。

    所以你可以尝试这样的事情:

     public class Reading
    {
    public string Temperature {get; set;}
    private double? _NumTemperature;
    public Double? NumTemperature{
    get{ return _NumTemperature} 
    set{
    Double n;
    bool isNumeric = double.TryParse(Temperature, out n);
    if (isNumeric)
    {
    _NumTemperature = n;
    }
    else
    {
    _NumTemperature = null;
    }
    }}
    }
    

    【讨论】:

      【解决方案4】:

      您可以如下修改您的类并使用Newtonsoft Json library 进行序列化/反序列化:

      public class Reading
      {
          [JsonIgnore]
          public double? Temperature { get; set; }
      
          [JsonProperty("temperature")]
          private string TemperatureString 
          {
              get
              {
                  return Temperature.HasValue ? Temperature.Value.ToString() :"NA";
              }
              set
              {
                  double result;
                  Temperature = double.TryParse(value, out result) ? result : null;
              }
          }
      }
      

      【讨论】:

        【解决方案5】:

        Json.NET 允许你create JsonConverter subclasses 处理特殊情况;你重写一些方法并将其传递给JsonConvert.Deserialise* 方法

        所以你的步骤是大致像这样创建一个类;

        public NAConverter: JsonConverter
        {
            public override bool CanConvert(Type t) { return t == typeof(string); }
            public override ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
            {
                ...
            }
        }
        

        然后,在 ReadJson 中,您将能够询问 JsonReader 是否指向字符串,以及是否为“NA”。如果是,则返回 null 或零或 Double.IsNaN;否则,遵从基地。

        然后将实例传递给JsonConvert.DeserializeObject()JsonConvert.Deserialize&lt;T&gt;()

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2014-03-14
          • 1970-01-01
          • 1970-01-01
          • 2012-04-09
          • 1970-01-01
          • 2020-05-20
          • 1970-01-01
          相关资源
          最近更新 更多