2013-04-10 12 views
9

Non sono sicuro del motivo per cui nessuno abbia ancora fatto domande su questa domanda, ma sto tentando di serializzare solo i tipi semplici di un dato oggetto utilizzando l'interfaccia IContractResolver. Non voglio davvero contrassegnare ogni proprietà utilizzando il metodo ShouldSerialize o JsonDataAttribute o qualcosa di simile.Serializzare solo tipi semplici utilizzando Json.Net

Quello che ho fatto finora indicato come segue sul LINQPad

Alcune classi di esempio per serializzare

class Customer 
{ 
    public List<Order> Orders {get;set;} 
    public int CustomerId {get;set;} 
    public string[] Addresses {get;set;} 
} 

class Order 
{ 
    public int OrderId{get;set;} 
    public string Name {get;set;} 
    public int Amount {get;set;} 
    public Order PreviousOrder {get;set;} 
} 

un metodo di estensione per serializzare tutti gli oggetti

static class ExtensionMethods 
{ 
    public static string JsonSerialize (this object obj) 
    { 
     var settings = new JsonSerializerSettings(); 
     settings.ContractResolver = new MyContractResolver(); 
     settings.DefaultValueHandling = DefaultValueHandling.Ignore; 
     settings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore; 
     return JsonConvert.SerializeObject(obj,settings); 
    } 
} 

My Custom Contract Resolver Class

public class MyContractResolver: DefaultContractResolver 
{ 
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) 
    { 
     var property = base.CreateProperty(member,memberSerialization); 
     property.ShouldSerialize = instance => instance.GetType().IsPrimitive || instance.GetType() == typeof(string) || instance.GetType() == typeof(decimal); 
     return property; 
    } 
} 

e metodo Main:

void Main() 
{ 
    var customer = new Customer 
       { 
        Orders = ProduceSomeOrders(), 
        Addresses = new string[] {"9450 S. Small Street Dr.","9521 Flintstone Dr. S"}, 
        CustomerId = 1 
       }; 

    var jsonOrder = customer.JsonSerialize(); 
    jsonOrder.Dump(); 
} 

voglio solo serializzare tipi di campioni come int, double, string, decimal, bool ecc ma non array, collezioni, oggetti personalizzati, ecc e naviga solo il primo livello, non il secondo o più livelli in basso. Mi chiedo davvero perché non c'è alcun metodo semplice che faccia questo in Json.Net.

Questa è l'uscita quando faccio funzionare questo codice: (un JSON vuoto)

{}

ho capito una cosa quando si esegue questo codice, il primo parametro member passato nel metodo CreateProperty è l'oggetto principale stesso che in questo caso è l'istanza Customer. Ma dal momento che questo funzionerà per tutti i tipi di tipi, non voglio dire instance.GetType() == typeof(Customer) o qualcosa del genere nel metodo. L'output previsto in questo caso è solo CustomerId in questo caso.

Conosci qualche modo elegante per gestire il mio problema?

+0

Qual è il risultato atteso della serializzazione? In base a ciò che ho letto, dovrebbe contenere solo CustomerID, è corretto? – Patrick

+0

@Patrick: hai ragione! – Tarik

+0

Nel metodo JsonSerialize, è possibile iterare le proprietà della "prima istanza", al fine di serializzare le sue proprietà figlio, e poi in qualche modo schiacciare insieme in una stringa json valida? – Patrick

risposta

5

Cambiando il metodo seguente ho ottenuto il risultato: {"CustomerId": 1}. E 'questo quello che stavi cercando?

public class MyContractResolver:DefaultContractResolver 
{ 
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization) 
{ 
    var property = base.CreateProperty(member,memberSerialization); 

    var propertyType = property.PropertyType; 
    if(propertyType == typeof(int) 
     || propertyType == typeof(string)){ 
     property.ShouldSerialize = instance => true; 
    } 
    else 
    { 
     property.ShouldSerialize = instance => false; 
    } 
    return property; 
} 
} 
2

Invece di metodo prioritario CreateProperty, sto prioritarie in GetSerializableObjects metodo in quanto dà tutti i possibili membri che avranno:

public class MyContractResolver: DefaultContractResolver 
{ 
    protected override List<MemberInfo> GetSerializableMembers(Type objectType) 
    { 
     var members = base.GetSerializableMembers(objectType); 
     var filteredMembers = new List<MemberInfo>(); 
     members.ForEach(m=>{ 
      if(m.MemberType == MemberTypes.Property) 
      { 
       PropertyInfo info = (PropertyInfo) m; 
       var type = info.PropertyType; 
       if(type.IsPrimitive || type == typeof(string) || type == typeof(decimal)) 
       { 
        filteredMembers.Add(m); 
       } 
      } 
     }); 
     return filteredMembers; 
    } 
} 
Problemi correlati