Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/15.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 将KeyValuePair自定义序列化为单个属性,而不是单独的;“关键”;及;“价值”;_C#_Json_Serialization - Fatal编程技术网

C# 将KeyValuePair自定义序列化为单个属性,而不是单独的;“关键”;及;“价值”;

C# 将KeyValuePair自定义序列化为单个属性,而不是单独的;“关键”;及;“价值”;,c#,json,serialization,C#,Json,Serialization,这就是我的问题。我有一门课看起来像这样 public class Record { public string Name { get; set; } public KeyValuePair<string, object> Details { get; set; } } { "Name" : "Root", "Details" : { "TestSerialization" : [ {

这就是我的问题。我有一门课看起来像这样

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" }
        ]
    }
}
{
    //...
    { "key" : "IsChild", "value" : true }
    //...
}
但似乎大多数序列化程序都会将键值对序列化为以下内容

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" }
        ]
    }
}
{
    //...
    { "key" : "IsChild", "value" : true }
    //...
}
是否有编写器或序列化程序可以完成此任务?

如果您愿意编写自定义转换器类,则内置的.NET可以为您提供所需的输出。每个框架版本的转换器的接口都有很大的不同,但总体思路是相同的。我将在这个答案中演示这两个方面

使用Json.Net 在Json.Net中,您需要实现这样一个类。
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();
    }
}
使用JavaScriptSerializer .Net版本的转换器称为。与Json.Net类似,
SupportedTypes
属性告诉
JavaScriptSerializer
转换器处理的对象类型,而
Serialize
方法负责重新格式化输出。主要区别在于,在
序列化
中,您不能直接控制JSON输出;相反,您构建并返回一个
IDictionary
,然后序列化程序将其序列化,以代替您正在转换的原始对象。所以不像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();
    }
}
类KvpJavaScriptConverter:JavaScriptConverter { 公共覆盖IEnumerable SupportedTypes { 获取{返回新列表{typeof(KeyValuePair)};} } 公共重写IDictionary序列化(对象obj、JavaScriptSerializer序列化程序) { KeyValuePair kvp=(KeyValuePair)obj; Dictionary dict=新字典(); dict.Add(kvp.Key,kvp.Value); 返回命令; } 公共重写对象反序列化(IDictionary dictionary、类型、JavaScriptSerializer序列化程序) { 抛出新的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);
    }
}
类程序
{
静态void Main(字符串[]参数)
{
var root=新记录
{
Name=“Root”,
详细信息=新的KeyValuePair(“TestSerialization”,
新名单
{
新的KeyValuePair(“IsChild”,true),
新的KeyValuePair(“Child1”,“另一对KV”)
})
};
var serializer=新的JavaScriptSerializer();
serializer.RegisterConverters(
新列表{new KvpJavaScriptConverter()});
string json=serializer.Serialize(根);
Console.WriteLine(json);
}
}

输出与Json.Net演示相同,只是JavaScriptSerializer不支持缩进输出

您可以直接使用
JavaScriptSerializer
进行序列化,查看我给出的示例。
JavaScriptSerializer
JsonConvert
,得到了相同的结果,我认为最好使用非第三方DDL,关键是当核心功能存在于
JSS
时,那么为什么要使用第三方DLL,你说什么?@ArindamNayak“关键是当JSS有核心功能时,为什么要使用第三方DLL,”。。。那么,莱蒂不在那里吗?这就是他的问题,不是吗?JSS和JsonConvert并没有做你们想让他们做的事情。@AlexAnderson,是的,我同意,重点是JSS和JSON.Net转换成一种相同的格式,具有
KeyValue
,这不是必需的,所以我仍然在寻找@Zacht的有用选项。这可以通过自定义转换器使用JavaScriptSerializer或JSON.Net来完成。我已经添加了一个详细的答案,说明如何进行。