Порядок сериализованных полей с использованием JSON.NET

Есть ли способ указать порядок полей в сериализованном объекте JSON с использованием JSON.NET ?

Достаточно указать, что одно поле всегда появляется первым.

Я выполнил JsonConvert.SerializeObject(key) метода JsonConvert.SerializeObject(key) через reflection (где ключ был IList) и обнаружил, что вызван JsonSerializerInternalWriter.SerializeList. Он принимает список и проходит через

for (int i = 0; i < values.Count; i++) { ...

где значения - это параметр IList.

Короткий ответ ... Нет, нет встроенного способа установить порядок, в котором поля указаны в строке JSON.

Поддерживаемый способ заключается в использовании атрибута JsonProperty для свойств classа, для которого вы хотите установить порядок. Подробнее читайте в документации по заказу JsonPropertyAttribute .

Передайте значение JsonProperty значение Order и сериализатор позаботится об остальном.

  [JsonProperty(Order = 1)] 

Это очень похоже на

  DataMember(Order = 1) 

дней System.Runtime.Serialization .

Фактически вы можете контролировать заказ, реализуя IContractResolver или переопределяя метод CreateProperties DefaultContractResolver .

Вот пример моей простой реализации IContractResolver который упорядочивает свойства по алфавиту:

 public class OrderedContractResolver : DefaultContractResolver { protected override System.Collections.Generic.IList CreateProperties(System.Type type, MemberSerialization memberSerialization) { return base.CreateProperties(type, memberSerialization).OrderBy(p => p.PropertyName).ToList(); } } 

Затем установите параметры и сериализуйте объект, а поля JSON будут в алфавитном порядке:

 var settings = new JsonSerializerSettings() { ContractResolver = new OrderedContractResolver() }; var json = JsonConvert.SerializeObject(obj, Formatting.Indented, settings); 

В моем случае ответ Маттиаса не сработал. Метод CreateProperties никогда не вызывался.

После некоторой отладки внутренних компонентов Newtonsoft.Json я придумал другое решение.

 public class JsonUtility { public static string NormalizeJsonString(string json) { // Parse json string into JObject. var parsedObject = JObject.Parse(json); // Sort properties of JObject. var normalizedObject = SortPropertiesAlphabetically(parsedObject); // Serialize JObject . return JsonConvert.SerializeObject(normalizedObject); } private static JObject SortPropertiesAlphabetically(JObject original) { var result = new JObject(); foreach (var property in original.Properties().ToList().OrderBy(p => p.Name)) { var value = property.Value as JObject; if (value != null) { value = SortPropertiesAlphabetically(value); result.Add(property.Name, value); } else { result.Add(property.Name, property.Value); } } return result; } } 

В моем случае решение niaher не работает, поскольку оно не обрабатывает объекты в массивах.

Основываясь на его решении, это то, что я придумал

 public static class JsonUtility { public static string NormalizeJsonString(string json) { JToken parsed = JToken.Parse(json); JToken normalized = NormalizeToken(parsed); return JsonConvert.SerializeObject(normalized); } private static JToken NormalizeToken(JToken token) { JObject o; JArray array; if ((o = token as JObject) != null) { List orderedProperties = new List(o.Properties()); orderedProperties.Sort(delegate(JProperty x, JProperty y) { return x.Name.CompareTo(y.Name); }); JObject normalized = new JObject(); foreach (JProperty property in orderedProperties) { normalized.Add(property.Name, NormalizeToken(property.Value)); } return normalized; } else if ((array = token as JArray) != null) { for (int i = 0; i < array.Count; i++) { array[i] = NormalizeToken(array[i]); } return array; } else { return token; } } } 

Как заметил Чарли, вы можете несколько контролировать порядок свойств JSON, заказывая свойства в самом classе. К сожалению, этот подход не работает для свойств, унаследованных от базового classа. Свойства базового classа будут упорядочены, поскольку они выложены в коде, но будут отображаться перед свойствами базового classа.

И для тех, кто задается вопросом, почему вы можете использовать алфавитные свойства JSON, намного проще работать с необработанными файлами JSON, особенно для classов с большим количеством свойств, если они упорядочены.

Следующий рекурсивный метод использует reflection для сортировки внутреннего списка токенов в существующем экземпляре JObject а не для создания нового отсортированного графа объектов. Этот код основан на внутренних деталях реализации Json.NET и не должен использоваться в производстве.

 void SortProperties(JToken token) { var obj = token as JObject; if (obj != null) { var props = typeof (JObject) .GetField("_properties", BindingFlags.NonPublic | BindingFlags.Instance) .GetValue(obj); var items = typeof (Collection) .GetField("items", BindingFlags.NonPublic | BindingFlags.Instance) .GetValue(props); ArrayList.Adapter((IList) items) .Sort(new ComparisonComparer( (x, y) => { var xProp = x as JProperty; var yProp = y as JProperty; return xProp != null && yProp != null ? string.Compare(xProp.Name, yProp.Name) : 0; })); } foreach (var child in token.Children()) { SortProperties(child); } } 

На самом деле, поскольку мой объект уже был JObject, я использовал следующее решение:

 public class SortedJObject : JObject { public SortedJObject(JObject other) { var pairs = new List>(); foreach (var pair in other) { pairs.Add(pair); } pairs.OrderBy(p => p.Key).ForEach(pair => this[pair.Key] = pair.Value); } } 

и затем используйте его следующим образом:

 string serializedObj = JsonConvert.SerializeObject(new SortedJObject(dataObject)); 

Если вы управляете (т.е. записываете) class, поместите свойства в алфавитном порядке, и они будут сериализованы в алфавитном порядке, когда JsonConvert.SerializeObject() .

В формате JSON нет порядка полей, поэтому определение порядка не имеет смысла.

{ id: 1, name: 'John' } эквивалентно { name: 'John', id: 1 } (оба представляют строго эквивалентный экземпляр объекта)

  • Регистрация пользовательского JsonConverter по всему миру в Json.Net
  • Строка Parse Json в C #
  • Json.net сериализует определенное частное поле
  • Как преобразовать datatable в строку json с помощью json.net?
  • Поиск конкретного JToken по имени в иерархии JObject
  • Как реализовать пользовательский JsonConverter в JSON.NET для десериализации списка объектов базового classа?
  • JSON.Net Xml Сериализация неправильно понимает массивы
  • Обнаружен цикл саморегуляции - Возврат данных из WebApi в браузер
  • JSON.net сериализуется непосредственно из oledbconnection
  • Как использовать JSON.NET для десериализации в вложенный / рекурсивный словарь и список?
  • ТипNameHandling предостережение в Newtonsoft Json
  • Давайте будем гением компьютера.