C#-将JSON反序列化为ValueTuple

我正在尝试将[{"foo": "1","bar": false},{"foo": "2","bar": false}]反序列化为List<(string,bool)>类型:

JsonConvert.DeserializeObject<List<(string foo,bool bar)>>(json)  

但始终获取默认值列表-(null,false)

如何实现正确的反序列化?

P.S。我对任何模型/类都不感兴趣。我需要精确地值元组。

jinsong0002 回答:C#-将JSON反序列化为ValueTuple

实现它的一种方法是使用JsonConverter。例如,

public class ValueTupleConverter<U,V> : Newtonsoft.Json.JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return typeof(ValueTuple<U,V>) == objectType;
    }

    public override object ReadJson(Newtonsoft.Json.JsonReader reader,Type objectType,object existingValue,Newtonsoft.Json.JsonSerializer serializer)
    {
        if (reader.TokenType == Newtonsoft.Json.JsonToken.Null) return null;

        var jObject = Newtonsoft.Json.Linq.JObject.Load(reader);
        var properties = jObject.Properties().ToList();
        return new ValueTuple<U,V>(jObject[properties[0].Name].ToObject<U>(),jObject[properties[1].Name].ToObject<V>());
    }

    public override void WriteJson(Newtonsoft.Json.JsonWriter writer,object value,Newtonsoft.Json.JsonSerializer serializer)
    {
        serializer.Serialize(writer,value);
    }

}

现在您可以按以下方式使用Converter。

var json = "[{'foo': '1','bar': false},{'foo': '2','bar': false}]";
var result = JsonConvert.DeserializeObject<IEnumerable<(string,bool)>>(json,new ValueTupleConverter<string,bool>());
foreach(var (foo,bar) in result)
{
   Console.WriteLine($"foo:{foo},bar:{bar}");
}

样本输出

foo:1,bar:False
foo:2,bar:False
,

创建了C#元组功能以表示值集,而不是实体。

值的名称类似于变量的名称。与变量名称一样,元组值名称仅存在于源代码中。

(string foo,bool bar)实际上只是ValueTuple<string,int>。就像(string bar,bool foo)

(string foo,bool bar) a = ('one',true);
(string bar,bool foo) b = a;

元组值存储在名为Item1Item2等的字段中。

亲自了解其工作原理here

如果您热衷于使用值元组,则必须对自己进行反序列化:

var json = "[{\"foo\": \"1\",\"bar\": false},{\"foo\": \"2\",\"bar\": false}]";

var jArray = JsonConvert.DeserializeObject<JArray> (json);

var list = new List<(string foo,bool bar)>();

foreach (var item in jArray)
{
    list.Add((item.Value<string>("foo"),item.Value<bool>("bar")));
}
,

在C#9中,您可以创建一个record并使用生成的解构函数来创建ValueTuple。我确实看到您不想声明模型,但这是我发现的最接近的方法:

声明记录:

private record FooBar(string foo,bool bar);

反序列化和解构:

(string foo,bool bar) = JsonConvert.DeserializeObject<FooBar>(json);

var (foo,bar) = JsonConvert.DeserializeObject<FooBar>(json);

,

我建议先将JSON转换为模型,然后将Deserialize转换为json

public class item
{
    public string foo { get; set; }
    public bool bar { get; set; }
}

方法1-使用foreach

using (StreamReader r = new StreamReader(filepath))
{
     string json = r.ReadToEnd();
     var obj = JsonConvert.DeserializeObject<List<item>>(json);

     Dictionary<string,bool> keyValuePairs = new Dictionary<string,bool>();
     foreach (var keyvalue in obj)
     {
          if (!keyValuePairs.ContainsKey(keyvalue.foo))
             keyValuePairs.Add(keyvalue.foo,keyvalue.bar);
     }
}

方法2-使用LINQ而不用担心重复

Dictionary<string,bool> keyValuePairs = JsonConvert.DeserializeObject<IEnumerable<item>>(json).ToDictionary(x => x.foo,x => x.bar);

方法3-通过考虑重复使用LINQ

Dictionary<string,bool> keyValuePairs = JsonConvert
                .DeserializeObject<IEnumerable<item>>(json)
                .GroupBy(p=>p.foo,StringComparer.OrdinalIgnoreCase)
                .ToDictionary(x => x.First().foo,x => x.First().bar);

方法4-使用DeserializeAnonymousType

 var definition = new[] {new { foo = "",bar = false } };
 string json = @"[{'foo': '1','bar': true}]";
 var obj = JsonConvert.DeserializeAnonymousType(json,definition).Select(p=> (p.foo,p.bar)).ToList();
本文链接:https://www.f2er.com/3008309.html

大家都在问