2016-05-01 4 views
1

Я пытаюсь десериализовать числовые данные с помощью Json.Net, где значение может быть указано как «NA», если оно отсутствует, например.Json.Net Deserializing «NA» для числовых значений

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

Я хотел бы разобрать значения в дважды?, т.е.

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

Где (чистый эффект) первое чтение из моего примера будет «75», а второй будет «нулевой».

У меня нет никакого контроля над JSON, который предоставляется мне.

Является ли JsonConverter единственным способом заставить Json.Net обрабатывать это для меня, или есть какой-то более простой способ? (Я всегда могу создать переменную частного класса для десериализованного значения Json, а затем добавить свое собственное общедоступное свойство, которое делает все, что я хочу для частного значения, но поскольку у меня есть много свойств, с которыми можно было бы справиться, было бы много дополнительного кода .)

+0

Вы можете использовать библиотеку JSon NewtonSoft в. – arrowd

ответ

0

Я предложил бы строить преобразователь пользовательского типа, но если вы действительно не хотите, вы можете 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(); 
    } 
} 
+0

Я столкнулся с этим в документации Json.Net. Оказывается, что можно указать преобразователь на каждое имущество основы:

// Новая Дата (976918263055) [JsonProperty] [JsonConverter (TypeOf (JavaScriptDateTimeConverter))] общественного DateTime LastModified {получить; задавать; } – BoCoKeith

+0

(Aargh. Извинения за плохое форматирование - недостаточно внимательно прочитали помощь.) – BoCoKeith

+0

@BoCoKeith: Да! Это определенно вариант. Что вы предпочитаете. –

0

В коде сервера введите температуру в своей модели, а затем используйте 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

0

Я не думаю, что есть способ иметь десериализатор преобразовать строку в обнуляемого дважды. Лучше десериализовать значение как строку, а затем обработать преобразование строки в числовое значение, когда вы ее используете.

так что вы могли бы попробовать что-то вроде этого:

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; 
} 
}} 
} 
0

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». Если это так, верните нулевой или нулевой или Double.IsNaN; в противном случае отложить до основания.

Затем передать экземпляр JsonConvert.DeserializeObject() или JsonConvert.Deserialize<T>()

0

Вы можете изменить свой класс следующим образом и использовать 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; 
     } 
    } 
} 
Смежные вопросы