所以这就是我的问题。我有一个看起来像这样的课......
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 }
//...
}
那里有作家或序列号可以做到这一点吗?
答案 0 :(得分:2)
如果您愿意编写自定义转换器类,Json.Net和内置.NET JavaScriptSerializer都可以为您提供所需的输出。每个框架的转换器版本的接口是完全不同的,但总体思路是相同的。我将在这个答案中展示两者。
在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"
}
]
}
}
.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不支持缩进输出。