[英]C# - deserialize JSON into ValueTuple
我正在尝试将[{"foo": "1", "bar": false}, {"foo": "2", "bar": false}]
List<(string, bool)>
化为List<(string, bool)>
类型:
JsonConvert.DeserializeObject<List<(string foo, bool bar)>>(json)
但总是得到一个默认值列表 - (null, false)
。
如何实现正确的反序列化?
PS 我对此目的的任何模型/类都不感兴趣。 我需要确切的值元组。
创建 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;
元组值存储在名为Item1
、 Item2
等的字段中。
在这里亲自看看它是如何工作的。
如果您热衷于为此使用值元组,则必须对自己进行反序列化:
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);
实现它的一种方法是使用 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);
}
}
现在您可以按如下方式使用转换器。
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
我建议先将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': false}, {'foo': '2', 'bar': true}]";
var obj = JsonConvert.DeserializeAnonymousType(json, definition).Select(p=> (p.foo, p.bar)).ToList();
您应该创建对象以反序列化
要在C#中反序列化Json,可能这是最好的方法。
从json创建模型,
public class Model
{
public string foo { get; set; }
public bool bar { get; set; }
}
使用该模型通过Newtonsoft Json反序列化
List<Model> data = JsonConvert.DeserializeObject<List<Model>>(jsonString);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.