将List〈KeyValuePair〈string,string>>序列化为JSON

chhqkbe1  于 2023-04-22  发布在  其他
关注(0)|答案(3)|浏览(154)

我对JSON很陌生,请帮忙!
我正在尝试将List<KeyValuePair<string, string>>序列化为JSON
目前:

[{"Key":"MyKey 1","Value":"MyValue 1"},{"Key":"MyKey 2","Value":"MyValue 2"}]

预期:

[{"MyKey 1":"MyValue 1"},{"MyKey 2":"MyValue 2"}]

我引用了thisthis的一些例子。
这是我的KeyValuePairJsonConverter:JsonConverter

public class KeyValuePairJsonConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        List<KeyValuePair<object, object>> list = value as List<KeyValuePair<object, object>>;
        writer.WriteStartArray();
        foreach (var item in list)
        {
            writer.WriteStartObject();
            writer.WritePropertyName(item.Key.ToString());
            writer.WriteValue(item.Value.ToString());
            writer.WriteEndObject();
        }
        writer.WriteEndArray();
    }

    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(List<KeyValuePair<object, object>>);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var jsonObject = JObject.Load(reader);
        var target = Create(objectType, jsonObject);
        serializer.Populate(jsonObject.CreateReader(), target);
        return target;
    }

    private object Create(Type objectType, JObject jsonObject)
    {
        if (FieldExists("Key", jsonObject))
        {
            return jsonObject["Key"].ToString();
        }

        if (FieldExists("Value", jsonObject))
        {
            return jsonObject["Value"].ToString();
        }
        return null;
    }

    private bool FieldExists(string fieldName, JObject jsonObject)
    {
        return jsonObject[fieldName] != null;
    }
}

我从一个WebService方法调用它,如下所示

List<KeyValuePair<string, string>> valuesList = new List<KeyValuePair<string, string>>();
Dictionary<string, string> valuesDict = SomeDictionaryMethod();

foreach(KeyValuePair<string, string> keyValue in valuesDict)
{
    valuesList.Add(keyValue);
}

JsonSerializerSettings jsonSettings = new JsonSerializerSettings { Converters = new [] {new KeyValuePairJsonConverter()} };
string valuesJson = JsonConvert.SerializeObject(valuesList, jsonSettings);
lymgl2op

lymgl2op1#

您可以使用Newtonsoft和字典:

var dict = new Dictionary<int, string>();
    dict.Add(1, "one");
    dict.Add(2, "two");

    var output = Newtonsoft.Json.JsonConvert.SerializeObject(dict);

输出为:

{"1":"one","2":"two"}

编辑

感谢**@Sergey别列佐夫斯基**提供的信息。
您当前使用的是Newtonsoft,因此只需将List<KeyValuePair<object, object>>更改为Dictionary<object,object>,并使用包中的serialize和deserialize方法。

bweufnob

bweufnob2#

所以我不想使用任何东西,但原生c#来解决类似的问题,作为参考,这是使用.net 4,jquery 3.2.1和 Backbone 1.2.0。
我的问题是List<KeyValuePair<...>>将从控制器处理到 Backbone.js 模型,但当我保存该模型时,控制器无法绑定List。

public class SomeModel {
    List<KeyValuePair<int, String>> SomeList { get; set; }
}

[HttpGet]
SomeControllerMethod() {
    SomeModel someModel = new SomeModel();
    someModel.SomeList = GetListSortedAlphabetically();
    return this.Json(someModel, JsonBehavior.AllowGet);
}

网络捕获:

"SomeList":[{"Key":13,"Value":"aaab"},{"Key":248,"Value":"aaac"}]

但是,即使在后台model.js中正确地设置了SomeList,试图保存模型而不对其进行任何更改,也会导致绑定SomeModel对象与请求主体中的参数具有相同的长度,但所有的键和值都为空:

[HttpPut]
SomeControllerMethod([FromBody] SomeModel){
    SomeModel.SomeList; // Count = 2, all keys and values null.
}

我唯一能找到的是KeyValuePair是一个结构,而不是可以以这种方式示例化的东西。我最终做的是:

  • 在某个地方添加一个包含键、值字段的Model Package 器:
public class KeyValuePairWrapper {
    public int Key { get; set; }
    public String Value { get; set; }

    //default constructor will be required for binding, the Web.MVC binder will invoke this and set the Key and Value accordingly.
    public KeyValuePairWrapper() { }

    //a convenience method which allows you to set the values while sorting
    public KeyValuePairWrapper(int key, String value)
    {
        Key = key;
        Value = value;
    }
}
  • 设置绑定类模型以接受自定义 Package 对象。
public class SomeModel
{
    public List<KeyValuePairWrapper> KeyValuePairList{ get; set }; 
}
  • 从控制器中获取一些JSON数据
[HttpGet]
SomeControllerMethod() {
    SomeModel someModel = new SomeModel();
    someModel.KeyValuePairList = GetListSortedAlphabetically();
    return this.Json(someModel, JsonBehavior.AllowGet);
}
  • 稍后执行某些操作,可能会调用model.save(null,...)
[HttpPut]
SomeControllerMethod([FromBody] SomeModel){
    SomeModel.KeyValuePairList ; // Count = 2, all keys and values are correct.
}
qxsslcnc

qxsslcnc3#

前面的答案都是正确的,但是它们太重了。它们没有充分利用Linq的一行程序。

让我们回顾一下上下文:

你可以从这个C#类型开始:

List<KeyValuePair<string, string>>

...一旦序列化,就变成了这个Json:

[{"Key":"MyKey 1","Value":"MyValue 1"},{"Key":"MyKey 2","Value":"MyValue 2"}]

...但你实际上想要这个Json:

[{"MyKey 1":"MyValue 1"},{"MyKey 2":"MyValue 2"}]

...这需要以下C#类型:

List<Dictionary<string, string>>

所以本质上你想把一个C#类型转换成另一个C#类型:

List<KeyValuePair<string, string>>   -->   List<Dictionary<string, string>>

注意:唯一有点烦人的部分是转换的这一点:

KeyValuePair<string, string>  -->   Dictionary<string, string>

因为据我所知,没有直接使用单个KeyValuePair来创建仅包含它的Dictionary的方法。您将在解决方案中看到,我首先将单个KVP放入仅包含它的列表中,然后使用ToDictionary。

  • 为了演示,* 我重新创建了你的C#输入:
var input = new List<KeyValuePair<string, string>>
{
            new KeyValuePair<string, string>("My Key 1", "MyValue1"),
            new KeyValuePair<string, string>("My Key2", "MyValue2")
};

然后您可以这样转换(一行解决方案):

var converted = input
    .Select(singleKvp => (new List<KeyValuePair<string, string>>() { singleKvp }).ToDictionary(x => x.Key, x => x.Value))
    .ToList(); // Optional

您可以使用以下命令测试结果:

var output = JsonSerializer.Serialize(converted);

相关问题