[英]JsonConvert.SerializeObject changes the sort order of fields in JSON
如果在子線程中對正在序列化的 object 調用.GetProperty
方法, JsonConvert.SerializeObject
會更改 JSON 中字段的排序順序。
class Program
{
static void Main(string[] args)
{
var tasks = new List<Task>();
for (int i = 0; i < 10; i++)
{
var task = Task.Factory.StartNew(() =>
{
var token = CreateRandomToken();
_ = typeof(TestObject).GetProperty("Version");
var str = JsonConvert.SerializeObject(token);
Console.WriteLine(str);
});
tasks.Add(task);
}
Task.WaitAll(tasks.ToArray());
Console.ReadLine();
}
private static TestObject CreateRandomToken()
=> new TestObject { TokenHash = "123456789", Name = "Name", Version = "123" };
}
public class TestObject
{
public string TokenHash { get; set; }
public string Name { get; set; }
public string Version { get; set; }
}
Version
字段在 JSON 的開頭,而不是結尾
如果我們刪除
_ = typeof(TestObject).GetProperty("Version");
如果我用屬性[JsonProperty (Order = 1)]
裝飾我的 object,那么排序將與我在屬性中指示的不同
我該如何解決? 不使用 attr [JsonProperty (Order = 1)]
進行修復
更新:我們使用 JSON 字符串來生成數字簽名,如果字段的順序發生更改,數字簽名將無效,因此字段的順序對我來說很重要
因為默認JsonSerializer
使用System.Type.GetProperties()
獲取屬性。
GetProperties 方法不按特定順序返回屬性,例如字母順序或聲明順序。 您的代碼不得依賴於返回屬性的順序,因為該順序會有所不同。 (源類型.GetProperties 方法)
在我看來,你不應該關心 Json 中的屬性順序。 如果 json 消費者真的需要這個合同,我認為你應該審查你的設計。
An object is an unordered collection of zero or more name/value pairs, where a name is a string and a value is a string, number, boolean, null, object, or array. (來源RFC 7159 )
事實證明JsonConvert.SerializeObject
不保證字段的默認順序。 要指定顯式排序,您可以使用DefaultContractResolver
謝謝安迪的主意!
自定義DefaultContractResolver
的實現:
public class OrderedContractResolver : DefaultContractResolver
{
private static ConcurrentDictionary<Type, IList<string>> _properties = new ConcurrentDictionary<Type, IList<string>>();
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
if (!_properties.TryGetValue(type, out var properties))
{
properties = type.GetProperties().Select(p => p.Name).ToList();
_properties.TryAdd(type, properties);
}
var jsonProperties = base.CreateProperties(type, memberSerialization).ToList();
var sorted = new List<JsonProperty>();
foreach (var property in properties)
{
var jsonProp = jsonProperties.FirstOrDefault(p => p.PropertyName == property);
if (jsonProp != null)
{
sorted.Add(jsonProp);
}
}
return sorted;
}
}
使用示例:
var jsonSerializerSettings = new JsonSerializerSettings {ContractResolver = new OrderedContractResolver()};
var str = JsonConvert.SerializeObject(token, jsonSerializerSettings);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.