将KeyValuePair自定义序列化为单个属性,而不是单独的“”;键“;以及“;值”;
本文关键字:单独 以及 序列化 自定义 KeyValuePair 单个 属性 | 更新日期: 2023-09-27 18:25:23
所以这是我的问题。我有一节课看起来像这样。。。
public class Record
{
public string Name { get; set; }
public KeyValuePair<string, object> Details { get; set; }
}
下面是一个实例的基本示例。。。
var root = new Record
{
Name = "Root",
Details = new KeyValuePair<string, object>("TestSerialization",
new List<KeyValuePair<string, object>>
{
new KeyValuePair<string, object>("IsChild", true),
new KeyValuePair<string, object>("Child1", "Another KV pair")
})
};
我想将这个对象序列化为JSON,但我想稍微修改一下这个过程。所以当我序列化这个对象时,我希望JSON看起来像这样。。。
{
"Name" : "Root",
"Details" :
{
"TestSerialization" :
[
{ "IsChild" : true },
{ "Child1" : "Another KV pair" }
]
}
}
但似乎大多数序列化程序都会将键值对序列化为这样的东西。。。
{
//...
{ "key" : "IsChild", "value" : true }
//...
}
有没有一个编写器或序列化程序可以实现这一点?
使用Json.Net
在Json.Net中,您需要实现这样的JsonConverter
类。CanConvert
方法告诉Json.Net转换器可以处理什么类型的对象,而WriteJson
方法则使用传递给该方法的JsonWriter
和JsonSerializer
将每个实例转换为Json。
class KvpConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(KeyValuePair<string, object>);
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
var kvp = (KeyValuePair<string, object>)value;
writer.WriteStartObject();
writer.WritePropertyName(kvp.Key);
serializer.Serialize(writer, kvp.Value);
writer.WriteEndObject();
}
public override bool CanRead
{
get { return false; }
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
以下是演示如何在序列化时使用转换器:
class Program
{
static void Main(string[] args)
{
var root = new Record
{
Name = "Root",
Details = new KeyValuePair<string, object>("TestSerialization",
new List<KeyValuePair<string, object>>
{
new KeyValuePair<string, object>("IsChild", true),
new KeyValuePair<string, object>("Child1", "Another KV pair")
})
};
var settings = new JsonSerializerSettings();
settings.Converters.Add(new KvpConverter());
settings.Formatting = Formatting.Indented;
string json = JsonConvert.SerializeObject(root, settings);
Console.WriteLine(json);
}
}
public class Record
{
public string Name { get; set; }
public KeyValuePair<string, object> Details { get; set; }
}
输出:
{
"Name": "Root",
"Details": {
"TestSerialization": [
{
"IsChild": true
},
{
"Child1": "Another KV pair"
}
]
}
}
使用JavaScriptSerializer
.Net版本的转换器称为JavaScriptConverter
。与Json.Net类似,SupportedTypes
属性告诉JavaScriptSerializer
转换器处理的对象类型,而Serialize
方法负责重新整形输出。主要区别在于,在Serialize
中,您不能直接控制JSON输出;相反,您构建并返回一个IDictionary<string, object>
,然后序列化程序将其序列化,以代替正在转换的原始对象。所以没有Json.Net那么灵活,但在这种情况下,它仍然足以满足我们的需求。以下是JavaScriptConverter:的代码
class KvpJavaScriptConverter : JavaScriptConverter
{
public override IEnumerable<Type> SupportedTypes
{
get { return new List<Type> { typeof(KeyValuePair<string, object>) }; }
}
public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
{
KeyValuePair<string, object> kvp = (KeyValuePair<string, object>)obj;
Dictionary<string, object> dict = new Dictionary<string, object>();
dict.Add(kvp.Key, kvp.Value);
return dict;
}
public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
{
throw new NotImplementedException();
}
}
这是更新的演示代码:
class Program
{
static void Main(string[] args)
{
var root = new Record
{
Name = "Root",
Details = new KeyValuePair<string, object>("TestSerialization",
new List<KeyValuePair<string, object>>
{
new KeyValuePair<string, object>("IsChild", true),
new KeyValuePair<string, object>("Child1", "Another KV pair")
})
};
var serializer = new JavaScriptSerializer();
serializer.RegisterConverters(
new List<JavaScriptConverter> { new KvpJavaScriptConverter() });
string json = serializer.Serialize(root);
Console.WriteLine(json);
}
}
输出与Json.Net演示相同,只是JavaScriptSerializer不支持缩进输出。