C# JSON 将字典序列化为 key:value, ... 而不是 key:key, value:value, ...

Posted

技术标签:

【中文标题】C# JSON 将字典序列化为 key:value, ... 而不是 key:key, value:value, ...【英文标题】:C# JSON Serialization of Dictionary into key:value, ... instead of key:key, value:value, ...C# JSON 将字典序列化为 key:value, ... 而不是 key:key, value:value, ... 【发布时间】:2011-06-19 04:03:32 【问题描述】:

是否可以使用 DataContractJsonSerializer 将 .Net Dictionary 序列化为 JSON,其格式为:


  key0:value0,
  key1:value1,
  ...

我使用字典 ,因为没有预定义的输入结构。

我对 DataContractJsonSerializer 结果很感兴趣!我已经找到了一个“Surrogate”的例子,但是输出中还有一个额外的“数据”,如果字典 是的话,转义也是假的。


我找到了解决方案,多么需要!首先,一个可序列化的“字典”类: (当然,这个示例只以一种方式工作,但我不需要反序列化)

[Serializable]
public class MyJsonDictionary<K, V> : ISerializable 
    Dictionary<K, V> dict = new Dictionary<K, V>();

    public MyJsonDictionary()  

    protected MyJsonDictionary( SerializationInfo info, StreamingContext context ) 
        throw new NotImplementedException();
    

    public void GetObjectData( SerializationInfo info, StreamingContext context ) 
        foreach( K key in dict.Keys ) 
            info.AddValue( key.ToString(), dict[ key ] );
        
    

    public void Add( K key, V value ) 
        dict.Add( key, value );
    

    public V this[ K index ] 
        set  dict[ index ] = value; 
        get  return dict[ index ]; 
    

用法:

public class MainClass 
    public static String Serialize( Object data ) 
        var serializer = new DataContractJsonSerializer( data.GetType() );
        var ms = new MemoryStream();
        serializer.WriteObject( ms, data );

        return Encoding.UTF8.GetString( ms.ToArray() );
    

    public static void Main() 
        MyJsonDictionary<String, Object> result = new MyJsonDictionary<String, Object>();
        result["foo"] = "bar";
        result["Name"] = "John Doe";
        result["Age"] = 32;
        MyJsonDictionary<String, Object> address = new MyJsonDictionary<String, Object>();
        result["Address"] = address;
        address["Street"] = "30 Rockefeller Plaza";
        address["City"] = "New York City";
        address["State"] = "NY";

        Console.WriteLine( Serialize( result ) );

        Console.ReadLine();
    

结果:


      "foo":"bar",
      "Name":"John Doe",
      "Age":32,
      "Address":
         "__type":"MyJsonDictionaryOfstringanyType:#Json_Dictionary_Test",
         "Street":"30 Rockefeller Plaza",
         "City":"New York City",
         "State":"NY"
      
   

【问题讨论】:

您想限制为DataContractJsonSerializer 的任何具体原因?每次我进行比较时(有好几次:我非常“喜欢”我的序列化程序),这对于 .NET 来说是最不受欢迎的 JSON 工具;我总是看 javascriptSerializer 或 JSON.Net 你在什么情况下使用这个?也就是说,这是一个 WCF 应用程序、ASP.NET 应用程序或其他东西。您使用 DataContractJsonSerilizer 的方式是您自己调用 WriteObject 还是某个框架为您执行此操作? 您的帖子中不清楚的是,您希望 1 个 JSON 对象,其属性(及其值)是字典中的名称/值对。无论是那个还是什么都是错误的,因为它不能是 JSON 数组,因为你不能有一个 JSON 数组,其中数组中的每个元素都有不同的属性名称。那么你能清楚你想要得到的实际格式吗? 有人发现相反的情况吗?如,如何让它正确反序列化MyJsonDictionary You shouldn't answer your own question in an edit。而是实际添加答案,请编辑您的问题并添加答案,作为答案 【参考方案1】:

Json.NET 会这样做...

Dictionary<string, string> values = new Dictionary<string, string>();
values.Add("key1", "value1");
values.Add("key2", "value2");

string json = JsonConvert.SerializeObject(values);
// 
//   "key1": "value1",
//   "key2": "value2"
// 

更多示例:Serializing Collections with Json.NET

【讨论】:

第二行应该是string values = JsonConvert.SerializeObject(values);【参考方案2】:

DataContractJsonSerializer 上使用属性UseSimpleDictionaryFormat 并将其设置为true

做的工作:)

【讨论】:

在序列化 http 响应时如何为 wcf 的默认行为设置这些设置? 为我工作,谢谢!我不得不在WebApiConfig.cs 中使用config.Formatters.JsonFormatter.UseDataContractJsonSerializer = true;【参考方案3】:

我在这段代码中使用了开箱即用的 MVC4(注意 ToDictionary 中的两个参数)

 var result = new JsonResult()
 
     Data = new
     
         partials = GetPartials(data.Partials).ToDictionary(x => x.Key, y=> y.Value)
     
 ;

我得到了预期的结果:

"partials":"cartSummary":"\u003cb\u003eCART SUMMARY\u003c/b\u003e"

重要提示:MVC4 中的 WebAPI 使用开箱即用的 JSON.NET 序列化,但标准 web JsonResult 操作结果没有。因此,我建议使用自定义 ActionResult 来强制 JSON.NET 序列化。你也可以得到很好的格式

这是一个简单的操作结果JsonNetResult

http://james.newtonking.com/archive/2008/10/16/asp-net-mvc-and-json-net.aspx

在序列化日期时,您会看到差异(并且可以确保您使用的是正确的):

微软方式:

 "wireTime":"\/Date(1355627201572)\/"

JSON.NET 方式:

 "wireTime":"2012-12-15T19:07:03.5247384-08:00"

【讨论】:

【参考方案4】:

在 .NET 5 及更高版本中,您可以简单地编写:

using System;
using System.Collections.Generic;
                    
public class Program

    public static void Main()
    
        Dictionary<string, string> values = new();
        values.Add("key1", "value1");
        values.Add("key2", "value2");

        string json = System.Text.Json.JsonSerializer.Serialize(values);
        Console.WriteLine(json);
    

获取"key1":"value1","key2":"value2"

没有外部依赖是needed。

【讨论】:

【参考方案5】:

很遗憾,目前在最新版本的 DataContractJsonSerializer 中无法做到这一点。见:http://connect.microsoft.com/VisualStudio/feedback/details/558686/datacontractjsonserializer-should-serialize-dictionary-k-v-as-a-json-associative-array

当前建议的解决方法是使用上面 Mark 建议的 JavaScriptSerializer。

祝你好运!

【讨论】:

【参考方案6】:

MyJsonDictionary 类对我来说效果很好,除了结果输出是 XML 编码的 - 所以“0”变成了 “0030”。 我和其他许多人一样,目前被困在 .NET 3.5 上,因此我无法使用许多其他解决方案。 “翻转图片”并意识到我永远无法说服 Microsoft 给我我想要的格式,但是... 字符串 json = XmlConvert.DecodeName(xmlencodedJson); 多田! 结果是您期望看到的 - 常规人类可读且非 XML 编码。 在 .NET 3.5 中工作。

【讨论】:

以上是关于C# JSON 将字典序列化为 key:value, ... 而不是 key:key, value:value, ...的主要内容,如果未能解决你的问题,请参考以下文章

JSON数组到字典

将json键值反序列化为字典c#

将json反序列化为键值对列表[重复]

打字稿->从Json.net转换字典的内容

使用 JsonConvert.DeserializeObject 或 JObject.Parse 将类反序列化为 c# 中的字典

Unity 将嵌套字典序列化为 JSON