如何在 Json.Net 中的 JsonConvert DeserializeObject 之后获取所有不存在的键?
Posted
技术标签:
【中文标题】如何在 Json.Net 中的 JsonConvert DeserializeObject 之后获取所有不存在的键?【英文标题】:How to get all not exist keys after JsonConvert DeserializeObject in Json.Net? 【发布时间】:2021-12-29 14:03:03 【问题描述】:您好,我正在使用 NewtonSoft Json.Net 反序列化我的 json 数据。我通常反序列化 json 字符串,但我想检查所有不存在的键。
例如这里是一个json数据。
"Hp": 100,
"PlayerInfo":
"Atk": 10,
"Def": 20
,
"Mp": 100
而且我有一个可以匹配上述数据的结构。
[Serializable]
public struct CharaData
public int Hp;
[Serializable]
public struct PlayerInfoData
public int Atk;
public int Def;
public int Spd;
PlayerInfoData PlayerInfo;
我会像这样对它进行去色化。
JsonConvert.DeserializeObject<CharaData>(jsonStr);
json 数据中有 Mp
键,但结构中没有。
在PlayerInfoData
中,json 数据中没有Spd
键,但在结构中有一个Spd
字段。
所以我想检查哪些键不在结构中。 以及哪些结构字段因为不存在而没有反序列化。
我会尽我所能防止这些发生,但是如果在从json数据反序列化的过程中缺少某些键,我会登录查找为什么没有反序列化的问题 完全成功。
[Error][CharaData::Mp key not exist in json string]
[Error][CharaData::PlayerInfo::Spd field not exist in struct]
似乎在 JsonConvert 类中没有任何方法可以检查它。 我看到了
[JsonProperty(Required = Required.Always)]
但这不会检查所有的键。 这个需要写自定义的json转换器吗?
【问题讨论】:
【参考方案1】:使用此代码
var result= JsonConvert.DeserializeObject<CharaData>(jsonStr);
var mp=result.Mp;
var playerInfo=result.PlayerInfo;
如果您想知道存在哪些键,只需检查它们是否为空。默认情况下,所有键都是空的。如果它们不为空,则表示它们从 json 中获取值。例如,您可以使用此代码
if (mp==null) Console.WriteLine ("mp is not exist in json");
另一种方法是使用反射检查所有属性
var props = result.GetType().GetProperties();
var nulls = new List<string>();
foreach (var prop in props)
var propInstance = prop.GetValue(result, null);
if (propInstance == null) nulls.Add(prop.Name);
if (prop.Name == "PlayerInfo")
var prps = prop.PropertyType.GetProperties();
foreach (var prp in prps)
if (prp.GetValue(propInstance, null) == null) nulls.Add(prop.Name+"."+prp.Name);
foreach (var n in nulls)
Console.WriteLine(n + " doesn't have value");
测试结果
PlayerInfo.Spd doesn't have value
类
public class PlayerInfo
public int? Atk get; set;
public int? Def get; set;
public int? Spd get; set;
public class CharaData
public int? Hp get; set;
public PlayerInfo PlayerInfo get; set;
public int? Mp get; set;
【讨论】:
【参考方案2】:你的问题是双重的:
-
查找缺失的字段
查找额外字段
在深入了解细节之前,让我们将CharaData
分为两个类
[Serializable]
public class CharaData
public int Hp;
public PlayerInfoData PlayerInfo;
[Serializable]
public class PlayerInfoData
public int Atk;
public int Def;
public int Spd;
缺少字段
此解决方案依赖于JsonSchema
private static Lazy<JSchema> schema = new Lazy<JSchema>(() =>
var generator = new JSchemaGenerator();
return generator.Generate(typeof(CharaData));
, true);
public static void ReportMissingFields(string json)
var semiParsed = JObject.Parse(json);
try
semiParsed.Validate(schema.Value);
catch (JSchemaValidationException ex)
Console.WriteLine(ex.ValidationError.Message);
schema
以惰性方式存储 CharaData
的 json 架构
Validate
将 json
与架构进行比较,如果不匹配,则抛出 JSchemaValidationException
它公开了一个类型为ValidationError
的属性,其中包含大量有关不匹配的信息
额外字段
此解决方案依赖于JsonExtensionDataAttribute
[Serializable]
internal class CharaDataExtras: CharaData
[JsonExtensionData]
public IDictionary<string, JToken> ExtraFields;
...
public static void ReportExtraFields(string json)
var result = JsonConvert.DeserializeObject<CharaDataExtras>(json);
foreach (var field in result.ExtraFields)
Console.WriteLine($"An extra field has found, called field.Key");
我已将CharaData
定义为能够从中派生的类CharaDataExtras
每个额外的字段都将被放入ExtraFields
字典中
用法
var json = File.ReadAllText("sample.json");
ReportMissingFields(json);
ReportExtraFields(json);
输出:
Required properties are missing from object: Spd.
An extra field has found, called Mp
【讨论】:
以上是关于如何在 Json.Net 中的 JsonConvert DeserializeObject 之后获取所有不存在的键?的主要内容,如果未能解决你的问题,请参考以下文章
如何在JSON.NET中读取json对象值中的long值数组
如何在 .net core 3.1 中的 Newtonsoft JsonConverter 中注入依赖项
如何使用与 NewtonSoft (JSON.Net) 组件中的 JSON 匹配的 Swift 类从/向 JSON 读取/写入对象数组?