回答
我随后经由反射JsonConvert.SerializeObject(key)
方法调用(其中键是一个IList),发现JsonSerializerInternalWriter.SerializeList被调用。它需要一个列表,并通过
for (int i = 0; i < values.Count; i++) { ...
其中值是IList的参数带来的遍历。
简短的回答是......不,没有内置的方法来设置字段的顺序列在JSON字符串中。
简短的回答,但可能过时。看看史蒂夫的回答(由詹姆斯牛顿王支持) – 2015-08-01 13:41:20
JSON格式的字段没有顺序,所以定义一个顺序是没有意义的。
{ id: 1, name: 'John' }
相当于{ name: 'John', id: 1 }
(两者都表示严格相等对象实例)
这只适用于“在线”传输,而不适用于另一端的消耗。一旦反序列化,基本上我并不期望命令持续存在。 – 2010-07-25 21:03:45
你在说什么? JSON是一种允许对象序列化/反序列化的格式。在OOP的对象字段中没有概念*顺序*。 – 2010-07-25 21:04:50
@Darin - 但是在序列化中有一个命令。 “{id:1,name:'John'}”and“{name:'John',id:1}”与* strings *不同,这就是我所关心的。当然,反序列化时对象是等价的。 – 2010-07-25 21:09:21
您可以通过执行IContractResolver
或覆盖DefaultContractResolver
的CreateProperties
方法实际控制订单。
这里是我的简单实现IContractResolver
的例子字母定购属性:
public class OrderedContractResolver : DefaultContractResolver
{
protected override System.Collections.Generic.IList<JsonProperty> 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);
完美地为我工作 – michaelAngelo 2012-11-14 14:54:26
谢谢!我正在找那个! – esskar 2013-03-16 18:15:42
这非常有用(+1),但有一点需要注意:它出现的字典序列化不会使用此CreateProperties自定义。他们序列化好,但不会最终排序。我假设有一种不同的方式来定制字典的序列化,但我还没有找到它。 – solublefish 2015-03-06 19:46:12
以下递归方法使用反射来对现有的JObject
实例上的内部令牌列表进行排序,而不是创建一个br和新的排序对象图。此代码依赖于内部的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<JToken>)
.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);
}
}
支持的方法是使用上要设置订单的类属性的属性JsonProperty
。 Read the JsonPropertyAttribute order documentation for more information。
通过JsonProperty
和Order
值,序列化程序将处理其余的。
[JsonProperty(Order = 1)]
这是非常相似的
DataMember(Order = 1)
的
System.Runtime.Serialization
天
。
使用'JsonPropertyAttribute'的'Order'属性可以控制字段序列化/反序列化的顺序。但是,如果您在所有其他属性上设置的订单大于1,则仅将订单设置为1。默认情况下,没有订单设置的任何属性将被赋予-1的顺序。所以你必须给所有序列化的属性和顺序,或者将你的第一项设置为-2。 – 2014-02-25 11:23:27
这个解决方案对我来说非常合适。^5 – 2015-07-16 21:58:33
它适用于序列化,但是在反序列化中没有考虑该顺序。根据文档,order属性用于序列化和反序列化。有没有解决方法? – cangosta 2015-12-21 18:46:36
在我的情况下,Mattias的答案没有奏效。 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;
}
}
这是使用字典时所需的修复方法。 – noocyte 2015-06-03 08:39:38
实际上,因为我的目标已经是一个JObject,我用以下解决方案:
public class SortedJObject : JObject
{
public SortedJObject(JObject other)
{
var pairs = new List<KeyValuePair<string, JToken>>();
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));
在我的情况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<JProperty> orderedProperties = new List<JProperty>(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;
}
}
}
如果你控制(即写入)类,把属性按字母顺序排列,他们将按照字母顺序序列化时JsonConvert.SerializeObject()
被调用。
查理指出,可以一定程度上受到的类本身订货属性控制JSON属性的排序。不幸的是,这种方法不适用于从基类继承的属性。基类属性将按照它们在代码中的布局进行排序,但会显示在基类属性之前。
而且任何人都知道为什么,你可能想按字母顺序排列JSON性能,它是一个整体更容易与原始JSON文件的工作,特别是对类有很多的属性,如果他们是有序的。
- 1. 序列化时的顺序字段
- 2. 如何使用Json.NET序列化C#中的“union-like”字段
- 3. 使用Json.NET反序列化
- 4. 序列化使用Json.NET
- 5. 使用json.Net序列化ExpandoObject
- 6. 反序列化使用json.net
- 7. 使用JSON.NET反序列化字典
- 8. 用Json.NET序列化
- 9. JSON.NET序列化
- 10. 使用JSON.Net反序列化为所有字段返回null(VB)
- 11. 使用Json.Net的序列化哈希表
- 12. 使用Json.NET序列化Vector2的数组
- 13. Json.NET:序列化/反序列化阵列
- 14. 序列化/反序列化JSON.NET的对象字典
- 15. 序列化/反序列化的字节数组中JSON.NET
- 16. JSON.NET反序列化
- 17. 序列化在JSON.NET
- 18. JSON.net反序列化
- 19. 如何使用Json.Net使用自定义键序列化/反序列化字典?
- 20. JSON.NET序列化的ProcessStartInfo
- 21. 用json.net反序列化JSON
- 22. 使用JSON.NET反序列化和序列化字典<字符串,对象>
- 23. 反序列化JSON.NET中值为字段名称的JSON
- 24. 有JSON.Net的JavaScript序列化程序吗?
- 25. JSON.NET序列化为阵列
- 26. Json.net只序列化阵列
- 27. 使用Json.Net反序列化Json对象
- 28. 使用Json.Net反序列化Instagram JSON
- 29. 如何使用Json.Net反序列化?
- 30. 使用JSON.Net序列化EF4.1实体
只是出于好奇,为什么你会在意吗? – 2012-07-03 10:41:44
我想他可能会首先显示ID字段(或类似字段),然后是所有其他字段。对于最终用户而言,这比对以A..I – michaelAngelo 2012-11-14 14:53:54
开头的字段之后的字符进行查找更友好.JSON属性被定义为无序。我认为在序列化过程中强制执行某个OUTPUT命令是绝对没问题的(也许是为了目击JSON),但是在反序列化的任何特定顺序上创建DEPENDENCY将是一个错误的决定。 – DaBlick 2015-06-30 12:58:28