Json.Net 为数值反序列化 "NA"
Json.Net Deserializing "NA" for Numeric Values
我正在尝试使用 Json.Net 反序列化数字数据,其中一个值可能被指定为 "NA" 如果它丢失,例如
{
"readings": [
{ "temperature" : 75 } ,
{ "temperature" : "NA" }
]
}
我想将值解析为 double? 类型,例如
public class Reading
{
public double? Temperature { get; set; }
}
我的示例中的第一个读数(净效应)为“75”,第二个读数为 "null"。
我无法控制提供给我的 JSON。
Json转换器是让 Json.Net 为我处理此问题的唯一方法吗,还是有更简单的方法? (我总是可以为 Json 反序列化值创建一个私有 class 变量,然后添加我自己的 public 属性 来对私有值做任何我想做的事情,但是正如我有很多属性来处理它会需要很多额外的代码。)
在您的服务器代码中,将温度设为模型中的字符串,然后使用 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
我认为没有办法让反序列化器将字符串转换为可为 null 的双精度值。最好将值反序列化为字符串,然后在使用时处理将字符串转换为数值。
所以你可以尝试这样的事情:
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;
}
}}
}
我建议构建一个自定义类型转换器,但如果您真的不想,您可以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 允许您create JsonConverter subclasses 处理特殊情况;您覆盖了一些方法并将其传递给 JsonConvert.Deserialise*
方法
所以您的步骤是创建一个 class 大致如此;
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"。如果是这样,return null 或零或 Double.IsNaN;否则,服从基地。
然后传递一个实例给JsonConvert.DeserializeObject()
或JsonConvert.Deserialize<T>()
您可以如下修改您的 class 并使用 Newtonsoft Json library 到 serialization/deserialization:
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;
}
}
}
我正在尝试使用 Json.Net 反序列化数字数据,其中一个值可能被指定为 "NA" 如果它丢失,例如
{
"readings": [
{ "temperature" : 75 } ,
{ "temperature" : "NA" }
]
}
我想将值解析为 double? 类型,例如
public class Reading
{
public double? Temperature { get; set; }
}
我的示例中的第一个读数(净效应)为“75”,第二个读数为 "null"。
我无法控制提供给我的 JSON。
Json转换器是让 Json.Net 为我处理此问题的唯一方法吗,还是有更简单的方法? (我总是可以为 Json 反序列化值创建一个私有 class 变量,然后添加我自己的 public 属性 来对私有值做任何我想做的事情,但是正如我有很多属性来处理它会需要很多额外的代码。)
在您的服务器代码中,将温度设为模型中的字符串,然后使用 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
我认为没有办法让反序列化器将字符串转换为可为 null 的双精度值。最好将值反序列化为字符串,然后在使用时处理将字符串转换为数值。
所以你可以尝试这样的事情:
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;
}
}}
}
我建议构建一个自定义类型转换器,但如果您真的不想,您可以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 允许您create JsonConverter subclasses 处理特殊情况;您覆盖了一些方法并将其传递给 JsonConvert.Deserialise*
方法
所以您的步骤是创建一个 class 大致如此;
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"。如果是这样,return null 或零或 Double.IsNaN;否则,服从基地。
然后传递一个实例给JsonConvert.DeserializeObject()
或JsonConvert.Deserialize<T>()
您可以如下修改您的 class 并使用 Newtonsoft Json library 到 serialization/deserialization:
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;
}
}
}