Json.NET 序列化 Dictionary<TKey, TValue> 与 KeyValuePair<TKey, TValue>
Json.NET serializing Dictionary<TKey, TValue> vs KeyValuePair<TKey, TValue>
考虑以下代码
var dict = new Dictionary<string, object>
{
{ "key 1", "value 1" },
{ "key 2", 123 }
};
var dictJson = JsonConvert.SerializeObject(dict); // yields {"key 1":"value 1","key 2":123}
var keyValuePair = dict.FirstOrDefault();
var keyValuePairJson = JsonConvert.SerializeObject(keyValuePair); // yields {"Key":"key 1","Value":"value 1"}
第一个问题是,为什么字典的第一个元素 KeyValuePair<TKey, TValue>
的 json 与 Dictionary<TKey, TValue>
的 json 不同?
第二个问题是,我怎样才能实现与序列化字典类似的 json 但只有一个项目而不是扩展集合?我的目标是有一个类似于下面的 class 但没有得到 Key
和 Value
作为序列化 json.
中的属性
public class Foo
{
public KeyValuePair<string, object> Pair { get; set; }
}
why is that the json of the first element of the dictionary, which is a KeyValuePair<TKey, TValue>
, different than the json of the Dictionary<TKey, TValue>
?
字典和键值对是非常不同的东西。字典 不只是 键值对的集合。当然,那是一本 观点 的词典,但是如果说词典只是那样就大错特错了。
更具体地说,NewtonsoftJson中有一个JsonConverter
,专门将KeyValuePair
转换为JSON,形式为:
{ "Key": ..., "Value": ... }
请注意,此形式将键和值都转换为 JSON,这很可能是您在转换“键 和 值时想要的" 到 JSON。将此与当字典的键不是字符串时字典转换器所做的比较 - 它只是调用 ToString
使其成为字符串:(
how can I achieve a similar json to the serialized dictionary but with only having one item instead of an extended collection?
你可以这样写JsonConverter
:
public class KeyValuePairObjectConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
{
JToken t = JToken.FromObject(value);
if (t.Type != JTokenType.Object)
{
t.WriteTo(writer);
}
else
{
JObject o = (JObject)t;
string key = o.Value<string>("Key");
var val = o["Value"];
writer.WriteStartObject();
writer.WritePropertyName(key);
val.WriteTo(writer);
writer.WriteEndObject();
}
}
public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
=> throw new NotImplementedException();
public override bool CanRead => false;
public override bool CanConvert(Type t)
{
if (t.IsValueType && t.IsGenericType)
{
return (t.GetGenericTypeDefinition() == typeof(KeyValuePair<,>)) &&
t.GetGenericArguments()[0] == typeof(string);
}
return false;
}
}
用法:
public class Foo
{
[JsonConverter(typeof(KeyValuePairObjectConverter))]
public KeyValuePair<string, object> Pair { get; set; }
}
考虑以下代码
var dict = new Dictionary<string, object>
{
{ "key 1", "value 1" },
{ "key 2", 123 }
};
var dictJson = JsonConvert.SerializeObject(dict); // yields {"key 1":"value 1","key 2":123}
var keyValuePair = dict.FirstOrDefault();
var keyValuePairJson = JsonConvert.SerializeObject(keyValuePair); // yields {"Key":"key 1","Value":"value 1"}
第一个问题是,为什么字典的第一个元素 KeyValuePair<TKey, TValue>
的 json 与 Dictionary<TKey, TValue>
的 json 不同?
第二个问题是,我怎样才能实现与序列化字典类似的 json 但只有一个项目而不是扩展集合?我的目标是有一个类似于下面的 class 但没有得到 Key
和 Value
作为序列化 json.
public class Foo
{
public KeyValuePair<string, object> Pair { get; set; }
}
why is that the json of the first element of the dictionary, which is a
KeyValuePair<TKey, TValue>
, different than the json of theDictionary<TKey, TValue>
?
字典和键值对是非常不同的东西。字典 不只是 键值对的集合。当然,那是一本 观点 的词典,但是如果说词典只是那样就大错特错了。
更具体地说,NewtonsoftJson中有一个JsonConverter
,专门将KeyValuePair
转换为JSON,形式为:
{ "Key": ..., "Value": ... }
请注意,此形式将键和值都转换为 JSON,这很可能是您在转换“键 和 值时想要的" 到 JSON。将此与当字典的键不是字符串时字典转换器所做的比较 - 它只是调用 ToString
使其成为字符串:(
how can I achieve a similar json to the serialized dictionary but with only having one item instead of an extended collection?
你可以这样写JsonConverter
:
public class KeyValuePairObjectConverter : JsonConverter
{
public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
{
JToken t = JToken.FromObject(value);
if (t.Type != JTokenType.Object)
{
t.WriteTo(writer);
}
else
{
JObject o = (JObject)t;
string key = o.Value<string>("Key");
var val = o["Value"];
writer.WriteStartObject();
writer.WritePropertyName(key);
val.WriteTo(writer);
writer.WriteEndObject();
}
}
public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
=> throw new NotImplementedException();
public override bool CanRead => false;
public override bool CanConvert(Type t)
{
if (t.IsValueType && t.IsGenericType)
{
return (t.GetGenericTypeDefinition() == typeof(KeyValuePair<,>)) &&
t.GetGenericArguments()[0] == typeof(string);
}
return false;
}
}
用法:
public class Foo
{
[JsonConverter(typeof(KeyValuePairObjectConverter))]
public KeyValuePair<string, object> Pair { get; set; }
}