2013-04-10 16 views
9

Nie jestem pewien, dlaczego ktoś jeszcze nie pytał o to pytanie, ale próbuję serializować tylko proste typy danego obiektu przy użyciu interfejsu IContractResolver. Naprawdę nie chcę oznaczać każdej właściwości przy użyciu metody ShouldSerialize lub JsonDataAttribute lub czegoś podobnego.Serializuj tylko proste typy przy użyciu Json.Net

co zrobiłem do tej pory przedstawione w następujący sposób na LINQPad

Niektóre przykładowe zajęcia do serializacji

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

metodę rozszerzenia do serializacji wszystkie obiekty

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

Moja niestandardowa rezolwerowa klasa

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

i metoda 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(); 
} 

chcę tylko do serializacji typów próbek takich jak int, double, string, decimal, bool itp ale nie tablice, kolekcje, niestandardowe obiekty itp i będzie nawigował tylko na pierwszym poziomie, a nie na 2. lub więcej poziomach w dół. Naprawdę zastanawiam się, dlaczego nie ma żadnej prostej metody, która robi to w Json.Net.

Jest to wyjście, kiedy uruchomić ten kod: (pusty json)

{}

Uświadomiłem sobie jedną rzecz, kiedy uruchomić ten kod, pierwszy member parametr przekazany w metodzie CreateProperty jest głównym obiektem, który w tym przypadku jest instancją Customer. Ale ponieważ będzie to działało dla wszystkich typów, po prostu nie chcę powiedzieć instance.GetType() == typeof(Customer) lub czegoś podobnego w metodzie. Oczekiwany wynik w tym przypadku to tylko CustomerId w tym przypadku.

Czy znasz jakiś zgrabny sposób radzenia sobie z moim problemem?

+0

Jaki jest oczekiwany wynik serializacji? Na podstawie tego, co przeczytałem, powinien zawierać tylko identyfikator klienta, czy to prawda? – Patrick

+0

@Patrick: Masz rację! – Tarik

+0

W metodzie JsonSerialize, możliwe jest iterowanie właściwości "najwyższej instancji", w celu serializowania jej właściwości podrzędnych, a następnie w jakiś sposób zacierania ich razem na prawidłowy ciąg json? – Patrick

Odpowiedz

5

Zmieniając poniższą metodę otrzymałem wynik: {"CustomerId": 1}. Czy tego właśnie szukałeś?

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

Zamiast nadrzędnym CreateProperty metody, ja nadrzędnymi GetSerializableObjects metody, ponieważ daje wszystkie możliwe członków będzie uzyskać:

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; 
    } 
} 
Powiązane problemy