2014-05-09 17 views
7

Sto scrivendo un app che ottiene un elenco Json di oggetti come questo:Deserialize JSON basato su campi in .Net (C#)

[ 
    { 
     "ObjectType": "apple", 
     "ObjectSize": 35, 
     "ObjectCost": 4, 
     "ObjectTaste": "good", 
     "ObjectColor": "golden" 
    }, 
    { 
     "ObjectType": "books", 
     "ObjectSize": 53, 
     "ObjectCost": 7, 
     "Pages": 100 
    }, 
    { 
     "ObjectType": "melon", 
     "ObjectSize": 35, 
     "ObjectTaste": "good", 
     "ObjectCost": 5 
    }, 
    { 
     "ObjectType": "apple", 
     "ObjectSize": 29, 
     "ObjectCost": 8, 
     "ObjectTaste": "almost good", 
     "ObjectColor": "red" 
    } 
    ] 

Voglio fare una classe base ItemToSell (dimensioni, costi) e ricava Apple, Melon e Book da esso, quindi effettua la deserializzazione basata sul campo "ObjectType" su qualsiasi classe che rientri. Voglio che crei una lista di oggetti ItemToSell, ogni oggetto sia Apple, Melone o Libro.

Come ho potuto farlo in. Net?

Grazie in anticipo :)

EDIT: So come deserializzare in una grande classe con tutti i campi si può mai contenere, come: Base(ObjectType,ObjectSize,ObjectCost,ObjectColor,Pages). Ma voglio distinguere tra le classi dal ObjectType quindi non avrò campi di utilità come il campo Pagine per ogni elemento del libro o ObjectTaste per ogni libro.

+0

non è JSON valida, assicurarsi che sia completo JSON –

risposta

12

Qualche tempo fa ho avuto lo stesso problema.

È possibile utilizzare Json.NET, ma se non si ha il controllo sul documento json (come in: 'è stato serializzato da qualche altro framework') è necessario creare un JsonConverter personalizzato come questo:

class MyItemConverter : JsonConverter 
{ 
    public override bool CanConvert(Type objectType) 
    { 
     return typeof(ItemToSell).IsAssignableFrom(objectType); 
    } 

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) 
    { 
     JObject obj = JObject.Load(reader); 
     string discriminator = (string)obj["ObjectType"]; 

     ItemToSell item; 
     switch (discriminator) 
     { 
      case "apple": 
       item = new Apple(); 
       break; 
      case "books": 
       item = new Books(); 
       break; 
      case "melon": 
       item = new Melon(); 
       break; 
      default: 
       throw new NotImplementedException(); 
     } 

     serializer.Populate(obj.CreateReader(), item); 

     return item; 

    } 


    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) 
    { 

    } 
} 

Poi è necessario aggiungerlo ai convertitori della JsonSerializerSettings in questo modo:

JsonSerializerSettings settings = new JsonSerializerSettings 
{ 
    TypeNameHandling = TypeNameHandling.Objects, 

}; 
settings.Converters.Add(new MyItemConverter()); 
var items = JsonConvert.DeserializeObject<List<ItemToSell>>(response, settings); 
+0

Grazie mille –

-1

Date un'occhiata a newtonsoft's JSON library

Con esso si possono fare cose come:

... 
public class Movie 
{ 
    public string Name; 
    public DateTime ReleaseDate; 
    public string[] Genres; 
} 
...... 

string json = @"{ 
    'Name': 'Bad Boys', 
    'ReleaseDate': '1995-4-7T00:00:00', 
    'Genres': [ 
    'Action', 
    'Comedy' 
    ] 
}"; 

Movie m = JsonConvert.DeserializeObject<Movie>(json); 

string name = m.Name; 
// Bad Boys 
+0

Ok so come convertire da JSON per classe C# e per deserializzare un oggetto, ma voglio che la creazione di oggetti in lista sulla base di ObjectType. Ma grazie per la risposta comunque. –

0

classe:

public class RootObject 
{ 
    public string ObjectType { get; set; } 
    public int ObjectSize { get; set; } 
    public int ObjectCost { get; set; } 
    public string ObjectTaste { get; set; } 
    public string ObjectColor { get; set; } 
    public int? Pages { get; set; } 
} 

Deserialize utilizzando NewtonSoft JSON biblioteca come questa:

var Jsonobject = JsonConvert.DeserializeObject<RootObject>(json); 
+1

Ok, so come convertire da Json a C# class e deserializzare un oggetto, ma voglio che crei oggetti nell'elenco basato su ObjectType. Grazie comunque: D –

+0

è un elenco di oggetti restituiti a destra –

+0

una volta ottenuti i dati nell'oggetto, allora puoi fare tutto il necessario –

1

Definire la classe base e le classi derivate.

l'uso [JSON.net] (disponibile anche tramite NuGet) 1 per deserializzare.

I.e.

class ItemToSell { 
string Type {get;set;} 
string Size {get;set;} 
string Cost {get;set;} 
} 

class Book : ItemToSell { ...} 

Poi deserializzare utilizzando

var catalog = JsonConvert.Deserialize<List<ItemToSell>>(json); 

Il deserializzatore ignorerà proprietà inaspettate. Chiamalo di nuovo usando un tipo specifico per ottenere altre proprietà se necessario.

2

questa non è una risposta, ma in C# 6.0 si sarà in grado di fare questo:

using Microsoft.VisualStudio.TestTools.UnitTesting; 
    using Newtonsoft.Json.Linq; 
    [TestMethod] 
    public void JsonWithDollarOperatorStringIndexers() 
    { 

     // Additional data types eliminated for elucidation 
     string jsonText = @" 
     { 
      'Byte': { 
      'Keyword': 'byte', 
      'DotNetClassName': 'Byte', 
      'Description': 'Unsigned integer', 
      'Width': '8', 
      'Range': '0 to 255' 
        }, 
      'Boolean': { 
      'Keyword': 'bool', 
      'DotNetClassName': 'Boolean', 
      'Description': 'Logical Boolean type', 
      'Width': '8', 
      'Range': 'True or false.' 
         }, 
     }"; 
     JObject jObject = JObject.Parse(jsonText); 
     Assert.AreEqual("bool", jObject.$Boolean.$Keyword); 
    } 

Tratto da here.

3

È possibile utilizzare un CustomCreationConverter.Ciò ti consente di collegarti al processo di deserializzazione.

public abstract class Base 
{ 
    public string Type { get; set; } 
} 

class Foo : Base 
{ 
    public string FooProperty { get; set; } 
} 

class Bar : Base 
{ 
    public string BarProperty { get; set; } 
} 

class CustomSerializableConverter : CustomCreationConverter<Base> 
{ 
    public override Base Create(Type objectType) 
    { 
     throw new NotImplementedException(); 
    } 

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

     var type = (string)jObject.Property("Type"); 
     Base target; 
     switch (type) 
     { 
      case "Foo": 
       target = new Foo(); 
       break; 
      case "Bar": 
       target = new Bar(); 
       break; 
      default: 
       throw new InvalidOperationException(); 
     } 
     serializer.Populate(jObject.CreateReader(), target); 
     return target; 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     var json = "[{Type:\"Foo\",FooProperty:\"A\"},{Type:\"Bar\",BarProperty:\"B\"}]"; 
     List<Base> bases = JsonConvert.DeserializeObject<List<Base>>(json, new CustomSerializableConverter()); 
    } 
}