无法将作业对象类型转换为字典<string, EntityProperty>
Cannot convert Jobject type to a Dictionary<string, EntityProperty>
如何将 JObject
转换为 Dictionary<string, EntityProperty>
。
我这样试过
data.ToObject<Dictionary<string, EntityProperty>>()
但它给我的错误是 ""将值“123”转换为类型 'Microsoft.Azure.Cosmos.Table.EntityProperty' 时出错。路径 'Version'."}""
我该怎么做?
调试时的 data 给我这个结构:
{
"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
]
}
您不能将问题中显示的 JSON 对象反序列化为 Dictionary<string, EntityProperty>
,即使 custom JsonConverter
. This is because EntityProperty
is a Class for storing information about a single property in an entity in a table. As such, it can capture a variety of .Net primitives including:
byte []
bool
DateTime
.
double
、int
和 long
.
string
但是,您的根 JSON 对象的值包括嵌套数组 ("RawSampleIDData"
) 和对象 ("Eest"
)。因此,它不能反序列化为 EntityProperty
基元的字典。您将需要采用不同的数据模型来反序列化 JSON.
相关的,见:
- insert complex objects to azure table with TableServiceEntity.
如果您的对象值完全是 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));
演示 fiddle 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
}
演示 fiddle #2 here.
如何将 JObject
转换为 Dictionary<string, EntityProperty>
。
我这样试过
data.ToObject<Dictionary<string, EntityProperty>>()
但它给我的错误是 ""将值“123”转换为类型 'Microsoft.Azure.Cosmos.Table.EntityProperty' 时出错。路径 'Version'."}""
我该怎么做? 调试时的 data 给我这个结构:
{
"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
]
}
您不能将问题中显示的 JSON 对象反序列化为 Dictionary<string, EntityProperty>
,即使 custom JsonConverter
. This is because EntityProperty
is a Class for storing information about a single property in an entity in a table. As such, it can capture a variety of .Net primitives including:
byte []
bool
DateTime
.double
、int
和long
.string
但是,您的根 JSON 对象的值包括嵌套数组 ("RawSampleIDData"
) 和对象 ("Eest"
)。因此,它不能反序列化为 EntityProperty
基元的字典。您将需要采用不同的数据模型来反序列化 JSON.
相关的,见:
- insert complex objects to azure table with TableServiceEntity.
如果您的对象值完全是 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));
演示 fiddle 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
}
演示 fiddle #2 here.