我正在尝试将[{"foo": "1","bar": false},{"foo": "2","bar": false}]
反序列化为List<(string,bool)>
类型:
JsonConvert.DeserializeObject<List<(string foo,bool bar)>>(json)
但始终获取默认值列表-(null,false)
。
如何实现正确的反序列化?
P.S。我对任何模型/类都不感兴趣。我需要精确地值元组。
我正在尝试将[{"foo": "1","bar": false},{"foo": "2","bar": false}]
反序列化为List<(string,bool)>
类型:
JsonConvert.DeserializeObject<List<(string foo,bool bar)>>(json)
但始终获取默认值列表-(null,false)
。
如何实现正确的反序列化?
P.S。我对任何模型/类都不感兴趣。我需要精确地值元组。
实现它的一种方法是使用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;
元组值存储在名为Item1
,Item2
等的字段中。
亲自了解其工作原理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();