2013-12-16 7 views
9

У меня есть код C# с использованием ASP.Net MVC, который использует Json.Net для сериализации некоторых DTO. Чтобы уменьшить полезную нагрузку, я использовал атрибут [JsonProperty (PropertyName = "shortName")] для использования более коротких имен свойств во время сериализации.Как игнорировать JsonProperty (PropertyName = "someName") при сериализации json?

Это отлично работает, когда клиент является другим .Net-приложением или сервисом, поскольку десериализация ставит иерархию объектов обратно, используя более удобные имена, сохраняя при этом фактическую полезную нагрузку передачи.

Проблема возникает, когда клиент является javascript/ajax через браузер. Он делает запрос и получает json ... но этот json использует сокращенные менее дружественные имена.

Как я могу заставить механизм сериализации json.net игнорировать атрибут [JsonProperty (PropertyName = "shortName")] программно? В идеале мой MVC-сервис будет сидеть там и обычно сериализоваться с использованием сокращенных имен свойств. Когда мой код обнаруживает определенный параметр, я хотел бы получить сериализацию данных с использованием более длинных имен и игнорировать атрибут [JsonProperty()].

Любые предложения?

Спасибо,

Kevin

+0

просто удалить 'JsonProperty' и возвращает анонимный объект по к параметру, который вы передали. что-то вроде 'new {UserName = uname}' –

+0

Я думаю, что лучшим подходом было бы сделать собственный сериализатор (с json.NET, а не с нуля) и удалить аннотации. Сделайте короткие имена и длинные имена параметром сериализатора и просто скажите, что вы хотите во время сериализации. json.NET не поддерживает использование/игнорирование аннотаций во время выполнения. Если они есть во время компиляции, они будут использоваться (запрет некоторых серьезных хакеров). – evanmcdonnal

+0

Я ценю комментарии там. @evanmcdonnal: если бы мы пошли с помощью специального сериализатора, нам нужно было бы это сделать на определенном DTO уровне (прикрепленном к каждому DTO?). У нас есть много DTO, распространяемых по многим решениям через наши многочисленные команды разработчиков. В идеале мы могли бы найти относительно элегантный способ подключения к процессу сериализации без необходимости касаться и поддерживать это через все DTO по всей доске. – Kevin

ответ

23

Это можно сделать довольно легко с помощью пользовательского контракта распознаватель. Вот весь код, вам нужно будет:

class LongNameContractResolver : DefaultContractResolver 
{ 
    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization) 
    { 
     // Let the base class create all the JsonProperties 
     // using the short names 
     IList<JsonProperty> list = base.CreateProperties(type, memberSerialization); 

     // Now inspect each property and replace the 
     // short name with the real property name 
     foreach (JsonProperty prop in list) 
     { 
      prop.PropertyName = prop.UnderlyingName; 
     } 

     return list; 
    } 
} 

Вот краткий демо с помощью распознаватель:

class Program 
{ 
    static void Main(string[] args) 
    { 
     Foo foo = new Foo 
     { 
      CustomerName = "Bubba Gump Shrimp Company", 
      CustomerNumber = "BG60938" 
     }; 

     Console.WriteLine("--- Using JsonProperty names ---"); 
     Console.WriteLine(Serialize(foo, false)); 
     Console.WriteLine(); 
     Console.WriteLine("--- Ignoring JsonProperty names ---"); 
     Console.WriteLine(Serialize(foo, true)); 
    } 

    static string Serialize(object obj, bool useLongNames) 
    { 
     JsonSerializerSettings settings = new JsonSerializerSettings(); 
     settings.Formatting = Formatting.Indented; 
     if (useLongNames) 
     { 
      settings.ContractResolver = new LongNameContractResolver(); 
     } 

     return JsonConvert.SerializeObject(obj, settings); 
    } 
} 

class Foo 
{ 
    [JsonProperty("cust-num")] 
    public string CustomerNumber { get; set; } 
    [JsonProperty("cust-name")] 
    public string CustomerName { get; set; } 
} 

Выход:

--- Using JsonProperty names --- 
{ 
    "cust-num": "BG60938", 
    "cust-name": "Bubba Gump Shrimp Company" 
} 

--- Ignoring JsonProperty names --- 
{ 
    "CustomerNumber": "BG60938", 
    "CustomerName": "Bubba Gump Shrimp Company" 
} 
Смежные вопросы