如何按特定顺序序列化和反序列化具有重复属性名的JSON对象



我需要创建一个C#类,用这样的括号来匹配这个json。

{
"data": {
"a": "4",
"b": "2",
"c": "3",
"a": "444",
},
}

System.Collections.Generic.Dictionary<string, string>做到了,但它不允许多个条目具有相同的密钥,所以这不起作用。

具有自定义数据类、字符串[2]、元组或值元组或KeyValuePair<string, string>List<T>创建不同的json,其中每个条目得到";项目1"项目1";或不同的括号。

如何反序列化和序列化这个确切的JSON?这是客户的";标准";我必须支持。

虽然在技术上没有格式错误,但最新的JSON RFC,RFC 8259:不推荐具有重复属性名的JSON对象

对象结构表示为一对围绕零个或多个名称/值对(或成员(的花括号。。。

名称都是唯一的对象是可互操作的,因为接收该对象的所有软件实现都将在名称值映射上达成一致当对象内的名称不唯一时,接收此类对象的软件的行为是不可预测的许多实现只报告姓氏/值对。其他实现报告错误或无法解析对象,而一些实现报告所有名称/值对,包括重复的名称/值。

您可能希望向客户建议一种替代的JSON格式,例如一个单键值对对象数组。

也就是说,如果必须序列化和反序列化具有重复属性的对象,Json.NET将不会开箱即用,您必须创建一个自定义JsonConverter才能手动执行此操作。由于JSON对象的值都是相同的类型(此处为字符串(,因此可以绑定到List<KeyValuePair<string, string>>

首先,定义以下模型:

public class Model
{
[JsonConverter(typeof(KeyValueListAsObjectConverter<string>))]
public List<KeyValuePair<string, string>> data { get; } = new ();
}

和以下通用JsonConverter<List<KeyValuePair<string, TValue>>>:

public class KeyValueListAsObjectConverter<TValue> : JsonConverter<List<KeyValuePair<string, TValue>>>
{
public override List<KeyValuePair<string, TValue>> ReadJson(JsonReader reader, Type objectType, List<KeyValuePair<string, TValue>> existingValue, bool hasExistingValue, JsonSerializer serializer)
{
if (reader.MoveToContentAndAssert().TokenType == JsonToken.Null)
return null;
reader.AssertTokenType(JsonToken.StartObject);
var list = existingValue ?? (List<KeyValuePair<string, TValue>>)serializer.ContractResolver.ResolveContract(objectType).DefaultCreator();
while (reader.ReadToContentAndAssert().TokenType != JsonToken.EndObject)
{
var name = (string)reader.AssertTokenType(JsonToken.PropertyName).Value;
var value = serializer.Deserialize<TValue>(reader.ReadToContentAndAssert());
list.Add(new KeyValuePair<string, TValue>(name, value));
}
return list;
}
public override void WriteJson(JsonWriter writer, List<KeyValuePair<string, TValue>> value, JsonSerializer serializer)
{
writer.WriteStartObject();
foreach (var pair in value)
{
writer.WritePropertyName(pair.Key);
serializer.Serialize(writer, pair.Value);
}
writer.WriteEndObject();
}
}
public static partial class JsonExtensions
{
public static JsonReader AssertTokenType(this JsonReader reader, JsonToken tokenType) => 
reader.TokenType == tokenType ? reader : throw new JsonSerializationException(string.Format("Unexpected token {0}, expected {1}", reader.TokenType, tokenType));

public static JsonReader ReadToContentAndAssert(this JsonReader reader) =>
reader.ReadAndAssert().MoveToContentAndAssert();
public static JsonReader MoveToContentAndAssert(this JsonReader reader)
{
if (reader == null)
throw new ArgumentNullException();
if (reader.TokenType == JsonToken.None)       // Skip past beginning of stream.
reader.ReadAndAssert();
while (reader.TokenType == JsonToken.Comment) // Skip past comments.
reader.ReadAndAssert();
return reader;
}
public static JsonReader ReadAndAssert(this JsonReader reader)
{
if (reader == null)
throw new ArgumentNullException();
if (!reader.Read())
throw new JsonReaderException("Unexpected end of JSON stream.");
return reader;
}
}

您将能够对问题中显示的JSON进行反序列化和重新序列化。

在这里演示小提琴。

相关内容

  • 没有找到相关文章

最新更新