如何解决反序列化 JSON,其中属性名称指示值的类型
我目前正在处理从外部 API 获取数据的问题。我收到的数据如下所示。 (只是一个模型;不要指望这些值有任何意义。这只是为了说明我得到的数据类型。)
{
"user": [
{
"key": "12345678","data": [
{
"id": "Name","string": "Bob"
},{
"id": "elapsedtimeSinceLastMessage","timestamp": 1618233964000
},{
"id": "Age","number": 27
}
]
}
]
}
我真的不知道我应该如何反序列化这个 JSON。
我现在用来反序列化的类如下所示:
public class User
{
[JsonProperty("key")]
public string Key { get; set; }
[JsonProperty("data")]
public List<DataEntry> DataEntries { get; set; }
}
public class DataEntry
{
[JsonProperty("id")]
public string Id { get; set; }
public Type Value { get; set; }
}
而且我不知道我需要设置什么才能反序列化 Value
中的 DataEntry
。也许有人可以引导我走向正确的方向?
解决方法
一个攻击角度是字典:
Check {1,2,3},odd_len? true
Check {4,5},odd_len? false
Check {6,7,8},odd_len? true
Processing {1,3,6,8}
After process: a:{1,4,9} b:{4,5} c:{36,49,64}
提取有点痛苦但可能:
public class WithUser
{
public List<User> User { get; set; }
}
public class User
{
[JsonProperty("key")]
public string Key { get; set; }
[JsonProperty("data")]
public List<Dictionary<string,object>> DataEntries { get; set; }
}
,
此 JSON 的 Data
部分实际上只是伪装的 Dictionary<string,object>
。您可以使用自定义 JsonConverter
将 ID/值对列表转换为易于使用的格式。
首先,定义这些类:
class RootObject
{
[JsonProperty("user")]
public List<User> Users { get; set; }
}
class User
{
public string Key { get; set; }
[JsonConverter(typeof(CustomDataConverter))]
public Dictionary<string,object> Data { get; set; }
}
接下来,定义转换器:
class CustomDataConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(Dictionary<string,object>);
}
public override object ReadJson(JsonReader reader,Type objectType,object existingValue,JsonSerializer serializer)
{
return JToken.Load(reader)
.Children<JObject>()
.ToDictionary(jo => (string)jo["id"],jo => jo.Properties()
.Where(jp => jp.Name != "id" && jp.Value is JValue)
.Select(jp => ((JValue)jp.Value).Value)
.FirstOrDefault());
}
public override bool CanWrite => false;
public override void WriteJson(JsonWriter writer,object value,JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
然后您可以像这样反序列化和转储数据:
var root = JsonConvert.DeserializeObject<RootObject>(json);
foreach (User user in root.Users)
{
Console.WriteLine("User Key: " + user.Key);
foreach (var kvp in user.Data)
{
Console.WriteLine(kvp.Key + ": " + kvp.Value);
}
}
这是一个工作演示:https://dotnetfiddle.net/GIT4dl
,主要问题在于您创建的模型。
首先,基于 JSON,您需要另一个包含用户列表的类。
public class ResultClass
{
public List<User> User { get; set; }
}
之后,因为data属性的第二个对象没有常量名,我们不能为其指定一个常量名(比如value)。我们应该将数据属性定义为一个对象。所以用户类应该是这样的:
public class User
{
[JsonProperty("key")]
public string Key { get; set; }
[JsonProperty("data")]
public List<object> DataEntries { get; set; }
}
最后,在控制器中,您应该反序列化 ResultJson 类:
var result = JsonConvert.DeserializeObject<ResultClass>(jsonTxt);
,
您可以使用 Json to C#。它从您的 json 字符串生成以下类。如您所见,您还可以使用可为空类型(long?
,int?
)。如果有值,则设置所需的变量。否则将其保留为空。这样,您就可以根据数据的 id 获取不同的类型。
public class DataEntry
{
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("string")]
public string String { get; set; }
[JsonProperty("timestamp")]
public long? Timestamp { get; set; }
[JsonProperty("number")]
public int? Number { get; set; }
}
public class User
{
[JsonProperty("key")]
public string Key { get; set; }
[JsonProperty("data")]
public List<DataEntry> Data { get; set; }
}
public class Root
{
public List<User> User { get; set; }
}
反序列化:
string response = "{\"user\":[{\"key\":\"12345678\",\"data\":[{\"id\":\"Name\",\"string\":\"Bob\"},{\"id\":\"ElapsedTimeSinceLastMessage\",\"timestamp\":1618233964000},{\"id\":\"Age\",\"number\":27}]}]}";
Root myDeserializedClass = JsonConvert.DeserializeObject<Root>(response);
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。