首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >如何在JsonConvert DeserializeObject in Json.Net之后获得所有不存在的密钥?

如何在JsonConvert DeserializeObject in Json.Net之后获得所有不存在的密钥?
EN

Stack Overflow用户
提问于 2021-11-18 17:08:43
回答 2查看 1K关注 0票数 0

你好,我正在使用NewtonSoft Json.Net反序列化我的json数据。我通常反序列化json字符串,但是我想检查所有不存在的键。

例如,这里有一个json数据。

代码语言:javascript
运行
复制
{
    "Hp": 100,
    "PlayerInfo": {
        "Atk": 10,
        "Def": 20
    },
    "Mp": 100
} 

我有一个结构可以与上面的数据相匹配。

代码语言:javascript
运行
复制
[Serializable]
public struct CharaData
{
    public int Hp;
    
    [Serializable]
    public struct PlayerInfoData
    {
       public int Atk;
       public int Def;
       public int Spd; 
    }
    PlayerInfoData PlayerInfo;
}

我要把它弄得像这样。

代码语言:javascript
运行
复制
JsonConvert.DeserializeObject<CharaData>(jsonStr);
  • json数据中有一个Mp键,但在结构上没有。
  • PlayerInfoData中,json数据中没有Spd键,但是在结构中有一个Spd字段。
代码语言:javascript
运行
复制
- _Well... Spd field seems initialize as a default 0 value and it could potentially be a bug._

所以我想检查哪些键不在结构中。以及哪些结构字段由于不存在而没有反序列化。

我将尽力防止这种情况发生,但是如果在从json数据反序列化的过程中缺少了一些键,我将记录下来,以找到反序列化为什么没有完全成功的问题。

代码语言:javascript
运行
复制
[Error][CharaData::Mp key not exist in json string]
[Error][CharaData::PlayerInfo::Spd field not exist in struct]

在JsonConvert类中似乎没有任何方法来检查它。我看到了

代码语言:javascript
运行
复制
[JsonProperty(Required = Required.Always)] 

但这并不能检查所有的钥匙。这需要编写自定义json转换器吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2021-11-19 08:56:51

你的问题有两个:

  1. 找出丢失的字段
  2. 找到额外的字段

在深入研究细节之前,让我们将CharaData分为两个类

代码语言:javascript
运行
复制
[Serializable]
public class CharaData
{
    public int Hp;
    public PlayerInfoData PlayerInfo;
}

[Serializable]
public class PlayerInfoData
{
    public int Atk;
    public int Def;
    public int Spd;
}

缺失场

此解决方案依赖于JsonSchema

代码语言:javascript
运行
复制
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架构。
  • Validatejson与模式进行比较,如果存在不匹配,则抛出一个JSchemaValidationException
    • 它公开一个类型为ValidationError的属性,该属性包含大量有关不匹配的信息。

额外字段

这个解决方案依赖于JsonExtensionDataAttribute

代码语言:javascript
运行
复制
[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字典中。

用法

代码语言:javascript
运行
复制
var json = File.ReadAllText("sample.json");
ReportMissingFields(json);
ReportExtraFields(json);

产出:

代码语言:javascript
运行
复制
Required properties are missing from object: Spd.
An extra field has found, called Mp
票数 0
EN

Stack Overflow用户

发布于 2021-11-18 17:14:53

使用此代码

代码语言:javascript
运行
复制
var result= JsonConvert.DeserializeObject<CharaData>(jsonStr);

var mp=result.Mp;
var playerInfo=result.PlayerInfo;

如果您想知道存在什么键,只需检查它们是否为null。默认情况下,所有键都为空。如果它们不是null,就意味着它们从json获得了值。例如,您可以使用以下代码

代码语言:javascript
运行
复制
if (mp==null) Console.WriteLine ("mp is not exist in json");

另一种方法是使用反射检查所有属性。

代码语言:javascript
运行
复制
    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");

测试结果

代码语言:javascript
运行
复制
PlayerInfo.Spd doesn't have value

代码语言:javascript
运行
复制
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; }
    }
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70023956

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档