如何解决无法将 Jobject 类型转换为 Dictionary<string, EntityProperty>
如何将 JObject
转换为 Dictionary<string,EntityProperty>
。
我试过这种方式
data.ToObject<Dictionary<string,EntityProperty>>()
但它给我错误说“”将值“123”转换为“Microsoft.Azure.Cosmos.Table.EntityProperty”的错误。路径“版本”。"}"
我该怎么做? 调试中的数据给了我这个结构:
{
"Version": "123","Eest": {
"Bulls": 1848,"Message": "Passed (0.325 mA < 2[0] => 'P')","Credit": 0.325,"Read": 0.14,"SBin": "P"
},"GenericTests": [],"HostVersion": "Test","RawSampleIDData": [
1,3,2,4
]
}
解决方法
即使使用 custom JsonConverter
,您也无法将问题中显示的 JSON 对象反序列化为 Dictionary<string,EntityProperty>
。这是因为 EntityProperty
是一个 Class用于在表中存储有关实体中单个属性的信息。因此,它可以捕获各种 .Net 原语 including:
byte []
bool
-
DateTime
。 -
double
、int
和long
。 string
但是,您的根 JSON 对象的值包括嵌套数组 ("RawSampleIDData"
) 和对象 ("Eest"
)。因此,它不能反序列化为 EntityProperty
原语字典。您将需要采用不同的数据模型来反序列化该 JSON。
相关见:
如果您的对象值完全是 JSON 原语,您可以引入以下转换器:
public class EntityPropertyConverter : JsonConverter<EntityProperty>
{
public override void WriteJson(JsonWriter writer,EntityProperty value,JsonSerializer serializer) =>
serializer.Serialize(writer,value.PropertyAsObject);
public override EntityProperty ReadJson(JsonReader reader,Type objectType,EntityProperty existingValue,bool hasExistingValue,JsonSerializer serializer)
{
switch (reader.MoveToContentAndAssert().TokenType)
{
case JsonToken.Null:
return null;
case JsonToken.Integer:
if (reader.Value is int i)
return new EntityProperty(i);
else if (reader.Value is long l)
return new EntityProperty(l);
// BigInteger not supported.
break;
case JsonToken.Float:
if (reader.Value is double d)
return new EntityProperty(d);
else if (reader.Value is decimal m)
return new EntityProperty((double)m);
break;
case JsonToken.String:
return new EntityProperty((string)reader.Value);
case JsonToken.Boolean:
return new EntityProperty((bool)reader.Value);
case JsonToken.Date:
if (reader.Value is DateTime dt)
return new EntityProperty(dt);
else if (reader.Value is DateTimeOffset dto)
return new EntityProperty(dto);
break;
case JsonToken.Bytes:
if (reader.Value is byte [] a)
return new EntityProperty(a);
else if (reader.Value is Guid g)
return new EntityProperty(g);
break;
}
throw new JsonSerializationException(string.Format("Cannot convert value {0} to {1}",reader.TokenType,nameof(EntityProperty)));
}
}
public static partial class JsonExtensions
{
public static JsonReader MoveToContentAndAssert(this JsonReader reader)
{
if (reader == null)
throw new ArgumentNullException();
if (reader.TokenType == JsonToken.None) // Skip past beginning of stream.
reader.ReadAndAssert();
while (reader.TokenType == JsonToken.Comment) // Skip past comments.
reader.ReadAndAssert();
return reader;
}
public static JsonReader ReadAndAssert(this JsonReader reader)
{
if (reader == null)
throw new ArgumentNullException();
if (!reader.Read())
throw new JsonReaderException("Unexpected end of JSON stream.");
return reader;
}
}
然后做:
var settings = new JsonSerializerSettings
{
Converters = { new EntityPropertyConverter() },};
var dict = data.ToObject<Dictionary<string,EntityProperty>>(JsonSerializer.CreateDefault(settings));
演示小提琴here。
更新
使用上述转换器,将任意 JObject
反序列化为 Dictionary<string,EntityProperty>
的一种选择是将对象展平为由每个原始值的 path 键控的字典,如下所示:
var settings = new JsonSerializerSettings
{
Converters = { new EntityPropertyConverter() },};
var serializer = JsonSerializer.CreateDefault(settings);
var dict = data.Descendants().OfType<JValue>().ToDictionary(v => v.Path,v => v.ToObject<EntityProperty>(serializer));
对于问题中的 JSON,结果是
{
"Version": "123","Eest.Bulls": 1848,"Eest.Message": "Passed (0.325 mA < 2[0] => 'P')","Eest.Credit": 0.325,"Eest.Read": 0.14,"Eest.SBin": "P","HostVersion": "Test","RawSampleIDData[0]": 1,"RawSampleIDData[1]": 3,"RawSampleIDData[2]": 2,"RawSampleIDData[3]": 4
}
演示小提琴 #2 here。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。