Как я могу изменить имена свойств при сериализации с Json.net?

434

У меня есть некоторые данные в объекте C # DataSet. Я могу сериализовать его прямо сейчас, используя конвертер Json.net, как это

DataSet data = new DataSet();
// do some work here to populate 'data'
string output = JsonConvert.SerializeObject(data);

Однако при этом используются имена свойств dataпри печати в файл .json. Я хотел бы изменить имена свойств на что-то другое (скажем, изменить 'foo' на 'bar').

В документации Json.net в разделе «Сериализация и десериализация JSON» → «Атрибуты сериализации» говорится «JsonPropertyAttribute ... позволяет настраивать имя». Но нет примера. Кто-нибудь знает, как использовать JsonPropertyAttribute, чтобы изменить имя свойства на что-то еще?

( Прямая ссылка на документацию )

Документация Json.net кажется скудной. Если у вас есть отличный пример, я постараюсь добавить его в официальную документацию. Спасибо!

culix
источник
3
К сведению, пример этого есть в документации в разделе Примеры -> Сериализация JSON -> Имя JsonPropertyAttribute . Не уверен, в какой момент он был добавлен.
Брайан Роджерс

Ответы:

791

Вы можете украсить желаемое свойство, контролируя его имя [JsonProperty]атрибутом, который позволяет вам указать другое имя:

using Newtonsoft.Json;
// ...

[JsonProperty(PropertyName = "FooBar")]
public string Foo { get; set; }

Документация: атрибуты сериализации

Дарин димитров
источник
1
Требуется ли для этого чтение данных в пользовательский объект, который я создаю, а не в DataSet?
Culix
3
@ Culix, да, это требует использования модели. DataSet - это слабо типизированная структура, поэтому говорить об именах свойств для него не очень логично.
Дарин Димитров
76
В качестве стенограммы, вы также можете сделать[JsonProperty("FooBar")]
Барт Verkoeijen
2
@DarinDimitrov есть ли способ сделать это без Json .NET?
CH81
13
Использовать модель очень просто, просто возьмите образец вашего JSON и вставьте его в пустой файл .cs, используя «Paste Special» -> «Вставить JSON как классы». - Он встроен в Visual Studio. - Оттуда вам в основном нужно просто настроить вещи как регистр заголовков / переименовать вещи, чтобы использовать соглашения об именах .NET и т. Д. (Используя конвертер прецедентов заголовка для первого и атрибут JsonProperty для второго).
BrainSlugs83
72

Если у вас нет доступа к классам для изменения свойств или вы не хотите всегда использовать одно и то же свойство переименования, переименование также можно выполнить путем создания специального распознавателя.

Например, если у вас есть класс с именем MyCustomObject, у которого есть свойство LongPropertyName, вы можете использовать собственный распознаватель, как этот…

public class CustomDataContractResolver : DefaultContractResolver
{
  public static readonly CustomDataContractResolver Instance = new CustomDataContractResolver ();

  protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
  {
    var property = base.CreateProperty(member, memberSerialization);
    if (property.DeclaringType == typeof(MyCustomObject))
    {
      if (property.PropertyName.Equals("LongPropertyName", StringComparison.OrdinalIgnoreCase))
      {
        property.PropertyName = "Short";
      }
    }
    return property;
  }
}

Затем вызовите сериализацию и предоставьте преобразователь:

 var result = JsonConvert.SerializeObject(myCustomObjectInstance,
                new JsonSerializerSettings { ContractResolver = CustomDataContractResolver.Instance });

И результат будет сокращен до {"Short": "prop value"} вместо {"LongPropertyName": "prop value"}

Больше информации о пользовательских резольверах здесь

StingyJack
источник
1
Это лучшее решение, если ваш класс для сериализации объявлен в другой сборке, которая включает другую версию пакета Newtonsoft.Json. (это может даже не выдать любую ошибку). DefaultContractResolverДолжен быть помещен в той же сборке , где используется метод JsonConvert.Serialize ().
Артемий
6

Есть еще один способ сделать это, используя конкретную NamingStrategy , которую можно применить к классу или свойству, украсив их с помощью [JSonObject]или [JsonProperty].

Существуют предопределенные стратегии именования CamelCaseNamingStrategy, но вы можете реализовать свои собственные.

Реализация различных стратегий именования может быть найдена здесь: https://github.com/JamesNK/Newtonsoft.Json/tree/master/Src/Newtonsoft.Json/Serialization

JotaBe
источник
3
Если вы можете, поделитесь примером пользовательской реализации
NamingStrategy
Конечно, нет. Вы должны были сделать это самостоятельно, но я сэкономлю вам время, чтобы сказать, что вам просто нужно унаследовать newtonsoft.com/json/help/html/… Вы можете увидеть реализацию существующих классов и создать свою собственную.
JotaBe
Спасибо - я должен был обновить свой комментарий: на самом деле, благодаря славе GitHub, можно использовать одну из собственных реализаций Newtonsoft в качестве примера, скажем, эту
user1007074
8
@JotaBe, это не дух переполнения стека. И как программист, который просто хочет, чтобы моя работа была выполнена, честно говоря, для меня было бы в тысячу раз лучше поднять код, который вы могли бы предоставить. И ты бы тоже получил мой голос. У меня 18-летний опыт программирования, и TripleByte оценивает меня как "эксперта" в c #. Не КАЖДУЮ проблему нужно оставлять как «упражнение для читателя». Иногда мы просто хотим делать свою работу и двигаться дальше.
bboyle1234
2
Я согласен с вами, и я обычно не пишу такого рода комментарии. Однако я могу заверить, что в этом случае рассмотрение связанного кода намного лучше, чем любое объяснение, которое я могу дать. И json.net - очень хорошо документированная библиотека с открытым исходным кодом. Включена ссылка на реализации (прекрасные примеры)
JotaBe