【问题标题】:Serialize a Dictionary<string,Type> and remove key/value from JSON string序列化 Dictionary<string,Type> 并从 JSON 字符串中删除键/值
【发布时间】:2013-08-08 16:21:37
【问题描述】:

我有以下代码 sn-p,其中我将对象序列化为 JSON。代码运行良好,但我想从 JSON 字符串中删除 KeyValue 关键字。

当前输出:

{
   "Description":"test",
   "RoomTypes":[
      {
         "Key":"A",
         "Value":{
            "Name":"Delux"
         }
      },
      {
         "Key":"B",
         "Value":{
            "Name":"Non delux"
         }
      }
   ],
   "Url":"http:\/\/test.com"
}

期望的输出:

{
   "Description":"test",
   "RoomTypes":[
      {
         "A":{
            "Name":"Delux"
         }
      },
      {
         "B":{
            "Name":"Non delux"
         }
      }
   ],
   "Url":"http:\/\/test.com"
}

我的测试代码:

namespace ConsoleApplication1
{
    [DataContract]
    public class Room
    {
        [DataMember]
        public string Url { get; set; }
        [DataMember]
        public string Description { get; set; }
        [DataMember]
        public Dictionary<string, RoomTypes> RoomTypes { get; set; }
    }

    [DataContract]
    public class RoomTypes
    {
        [DataMember]
        public string Name { get; set; }
    }

    public class Test
    {
        static void Main(string[] args)
        {
            Room room = new Room { Url = "http://test.com", Description="test" };
            RoomTypes roomType1 = new RoomTypes() { Name = "Delux" };
            RoomTypes roomType2 = new RoomTypes() { Name = "Non delux" };
            room.RoomTypes = new Dictionary<string, RoomTypes>();
            room.RoomTypes["A"] = roomType1;
            room.RoomTypes["B"] = roomType2;

            DataContractJsonSerializer dataContractSer = 
                   new DataContractJsonSerializer(typeof(Room));
            StringBuilder sb = new StringBuilder();
            MemoryStream ms = new MemoryStream();
            dataContractSer.WriteObject(ms, room);
            var result = Encoding.UTF8.GetString(ms.ToArray());
            Console.WriteLine(result);
        }
    }
}

有没有办法做到这一点?

【问题讨论】:

  • @Brian: 啊——我只是在发帖后才检查...你复活了一个 3 年前的问题... :-)

标签: c# json datacontractserializer


【解决方案1】:

这不好玩,但试试这个:

[Test]
public void Json()
{
         var input = @"{
   ""Description"":""test"",
   ""RoomTypes"":[
      {
         ""Key"":""A"",
         ""Value"":{
            ""Name"":""Delux""
         }
      },
      {
         ""Key"":""B"",
         ""Value"":{
            ""Name"":""Non delux""
         }
      }
   ],
   ""Url"":""http:\/\/test.com""
}";

    var temp = JsonConvert.DeserializeObject<Temp>(input);
    var transform = new Transform
        {
            Description = temp.Description,
            Url = temp.Url,
            RoomTypes = new List<IDictionary<string, Temp.NameObj>>()
        };

    foreach (var group in temp.RoomTypes)
    {
        var dic = new Dictionary<string, Temp.NameObj> {{@group.Key, @group.Value}};
        transform.RoomTypes.Add(dic);
    }

    Console.WriteLine(JsonConvert.SerializeObject(transform));
}

public class Transform
{
    public string Description { get; set; }
    public IList<IDictionary<string, Temp.NameObj>> RoomTypes { get; set; }
    public string Url { get; set; }
}


public class Temp
{
    public string Description { get; set; }
    public IList<GroupObj> RoomTypes { get; set; }
    public string Url { get; set; }

    public class GroupObj
    {
        public string Key { get; set; }
        public NameObj Value { get; set; }
    }

    public class NameObj
    {
        public string Name { get; set; }
    }
}    

思路是利用Json.Net的字典序列化来实现你想要的结构。

【讨论】:

  • 不使用Json.Net可以吗?
  • 我刚刚使用 DataContractJsonSerializer 对其进行了测试,它不会按照您想要的方式进行序列化。它将返回如下内容:"RoomTypes":[[{"Key":"A","Value":{"Name":"Delux"}}]。如果您尝试使用 ExpandoObject,它将在序列化级别失败。我不确定如何使用 DataContractJsonSerializer 来做到这一点:(
【解决方案2】:

如果您使用 .NET Framework v4.5 或更高版本,您可以将 DataContractJsonSerializerSettings.UseSimpleDictionaryFormat 设置为 true 以更接近您想要的格式:

var settings = new DataContractJsonSerializerSettings();
settings.UseSimpleDictionaryFormat = true;

var dataContractSer = new DataContractJsonSerializer(typeof(Room), settings);

使用带有上述修改的问题中的测试代码会产生以下输出,可能就是您要查找的内容(尽管它与问题中所述的所需输出不同):

{
  "Description": "test",
  "RoomTypes": {
    "A": {
      "Name": "Delux"
    },
    "B": {
      "Name": "Non delux"
    }
  },
  "Url": "http://test.com"
}

【讨论】:

  • 我花了一段时间才得到这个答案。我不想在我的项目中添加另一个依赖项 just 以便能够从 JSON 文件中读取键值对。谢谢!
【解决方案3】:

这是因为您使用字典来存储值。您必须编写自定义实现并覆盖序列化/反序列化方法

查看here了解更多详情

【讨论】:

    【解决方案4】:

    我知道您不想使用 Json.NET,但说真的,这是专门为处理 JSON 序列化而构建的库。 Json.NET 完全满足您的要求,您只需将其编写为一行代码...

    (来自文档:)

    Dictionary<string, int> points = new Dictionary<string, int>
    {
        { "James", 9001 },
        { "Jo", 3474 },
        { "Jess", 11926 }
    };
    
    string json = JsonConvert.SerializeObject(points, Formatting.Indented);
    
    Console.WriteLine(json);
    // {
    //   "James": 9001,
    //   "Jo": 3474,
    //   "Jess": 11926
    // }
    

    http://www.newtonsoft.com/json/help/html/serializedictionary.htm

    【讨论】:

      【解决方案5】:

      你可以用字符串替换函数来修改你的字符串试试这个

      >   public string updatejson (string jsonorg)
      >     {
      >         string updatedjson = "";
      >         updatedjson = jsonorg.Replace("\"Key\":", "");
      >         updatedjson = updatedjson.Replace("\"Value\":", "");
      >         updatedjson = updatedjson.Replace("\",", "\":");
      >         updatedjson = updatedjson.Replace("},{", ",");
      >         updatedjson = updatedjson.TrimStart('[');
      >         updatedjson = updatedjson.TrimEnd(']');
      > 
      >         return updatedjson;
      >     }
      

      【讨论】:

      • 很抱歉,这是一个非常脆弱的解决方案,并且会根据源 JSON 的格式和/或内容生成无效的 JSON。有关示例,请参见 dotnetfiddle.net/JiwLN5
      • 是的,我知道这件事。我们必须根据要求修改我们的代码。我并不是说这是我只分享了针对此类问题的快速解决方案的解决方案。
      猜你喜欢
      • 2014-01-10
      • 2011-07-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-17
      • 2022-01-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多