2015-05-10 17 views
9

Esiste un modo per serializzare una proprietà dell'oggetto Json che varia da decimale a decimale [] in una singola operazione?Serializzare una proprietà Json che a volte è una matrice

Nel mio feed prodotto Json le offerte speciali sono rappresentate come una matrice (prezzo normale/prezzo di vendita). Gli oggetti normali sono solo il prezzo. In questo modo:

[ 
    { 
     "product" : "umbrella", 
     "price" : 10.50, 
    }, 
     "product" : "chainsaw", 
     "price" : [ 
         39.99, 
         20.0 
        ] 
    } 
] 

L'unico modo in cui posso farlo funzionare è se faccio la proprietà di un oggetto in questo modo:

public class Product 
{ 
    public string product { get; set; } 
    public object price { get; set; } 
} 

var productList = JsonConvert.DeserializeObject<List<Product>>(jsonArray); 

Ma se provo a farlo Decimale [] allora sarà lanciare un'eccezione su un singolo valore decimale. Rendendolo un oggetto significa che i valori degli array sono un JArray quindi devo fare qualche lavoro di ripulitura in seguito e altri mapping nella mia applicazione richiedono che il tipo di proprietà sia accurato quindi devo mapparlo a una proprietà non mappata e quindi inizializzare un'altra proprietà che non è un grosso problema ma un po 'disordinato con i nomi.

L'oggetto è l'unica opzione qui o c'è un po 'di magia che posso fare con il serializzatore che aggiunge un singolo valore all'array o il secondo valore a una proprietà separata per un prezzo speciale di offerta?

+0

Invece di usare '' object' provare dinamica 'ie' prezzo dinamico pubblico {get; impostato; } ' –

risposta

14

Devi scrivere un convertitore personalizzato per quel price proprietà (perché non è in formato bene), e utilizzare in questo modo:

public class Product 
    { 
     public string product { get; set; } 
     [JsonConverter(typeof(MyConverter))] 
     public decimal[] price { get; set; } 
    } 


public class MyConverter : JsonConverter 
    { 
     public override bool CanConvert(Type objectType) 
     { 
      return false; 
     } 

     public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
     { 
      if(reader.TokenType == JsonToken.StartArray) 
      { 
       return serializer.Deserialize(reader, objectType); 
      } 
      return new decimal[] { decimal.Parse(reader.Value.ToString()) };    
     } 

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

E quindi analizzare come di consueto:

var productList = JsonConvert.DeserializeObject<List<Product>>(jsonStr); 
+0

Devi specificare l'attributo sul tipo se stai inviando' MyConverter() 'come parametro sul metodo deserialize? –

+0

elegante! lo adoro :) –

+0

questo è adorabile! –

3

altro Il modo per fare ciò è aggiungere un campo Json che sia dynamic e contrassegnarlo con l'attributo JsonProperty in modo che si allinei con il Json effettivo. Poi hanno il campo reale nel .NET che si terrà quel campo JSON e tradurlo in un array vero e proprio in questo modo ...

using System; 
using System.Linq; 
using System.Collections.Generic; 
using Newtonsoft.Json; 
using Newtonsoft.Json.Linq; 

public class Program 
{ 
    public static void Main() 
    { 
     var json = "{ \"price\": [ 10, 20 ] }"; 
     var json2 = "{ \"price\": 15 }"; 

     var foo1 = JsonConvert.DeserializeObject<Foo>(json); 
     var foo2 = JsonConvert.DeserializeObject<Foo>(json2); 

     foo1.Price.ForEach(Console.WriteLine); 
     foo2.Price.ForEach(Console.WriteLine); 
    } 
} 

public class Foo { 
    [JsonProperty(PropertyName = "price")] 
    public dynamic priceJson { get; set; } 

    private List<int> _price; 

    public List<int> Price { 
     get { 
      if (_price == null) _price = new List<int>(); 

      _price.Clear(); 

      if (priceJson is Newtonsoft.Json.Linq.JArray) { 

       foreach(var price in priceJson) { 
        _price.Add((int)price); 
       } 
      } else { 
       _price.Add((int)priceJson); 
      } 

      return _price; 
     } 
    } 
} 

campione Live at: https://dotnetfiddle.net/ayZBlL

+0

Grazie !. Ho usato una combinazione di questo approccio e il convertitore personalizzato – Guerrilla

Problemi correlati