如何检查Json对象是否已填充所有值

时间:2017-10-20 17:45:24

标签: c# json json.net json-deserialization

我从外部api获取一个大的嵌套json对象。我想确保所有字段都填充在该json对象中。有没有可用的图书? Newtonsoft.JsonJToken类,用于检查Json的架构是否有效,但我找不到任何方法来检查json对象中的所有字段是否都已填满。

场景:我正在构建一个api,用于收集有关某个人或实体的信息。有许多信息来源。我需要继续搜索数据,直到所需的对象已满。所以先调用api1,获取一些数据,检查对象是否已满。如果对象未满,则转到api2,依此类推。所以在对象满了之后调用会返回。 一个关键点是所需的对象架构不是静态的。

我可以将它反序列化为POCO并遍历每个嵌套对象,但我正在寻找更好的解决方案。

任何建议都受到高度赞赏。

2 个答案:

答案 0 :(得分:2)

如果我理解正确,你有一些复杂的JSON对象,带有一组必需和不需要的属性。

我在这里看到三个解决方案:

  1. 您已经提到过JSON模式验证。以下是其中一个实现:Json.NET Schema
  2. 创建POCO对象并使用相应的Required / Not-Required属性标记所有属性。在这种情况下,如果json-string不包含任何必需数据,您将获得异常。例如,它是如何根据Json.NET's JsonPropertyAttribute

    完成的
    [JsonObject]
    public class PocoObject
    {
        [JsonProperty("$schema", Required = Required.Default, NullValueHandling = NullValueHandling.Ignore)]
        public string Schema { get; set; }
    
        [JsonProperty("name", Required = Required.Always)]
        public string Name { get; set; }
    
        [JsonProperty("properties", Required = Required.Always)]
        public MorePropertiesObject Properties { get; set; }
    }
    

    作为奖励,您可以添加自定义属性,方法,转换器等

  3. 将原始json反序列化为类似字典的结构,并使用您自己的手写验证器对其进行验证。类似的东西:

    try
    {
        var jo = JObject.Parse(jsonString);
        Contract.Assert(!string.IsNullOrEmpty(jo["root"]["prop1"].ToString()));
        Contract.Assert(!string.IsNullOrEmpty(jo["root"]["prop2"].ToString()));
    }
    catch (JsonReaderException) { }
    catch (JsonSerializationException) { }
    
  4. 提供的代码示例供您Newtonsoft.Json

    提及

答案 1 :(得分:2)

如果您有一个JSON字符串并且只想检查任何属性值或数组项是否为null,则可以解析为JToken,以{递归方式下降JToken层次结构{ {3}},并使用以下扩展方法检查每个JValue是否为null

public static partial class JsonExtensions
{
    public static bool AnyNull(this JToken rootNode)
    {
        if (rootNode == null)
            return true;
        // You might consider using some of the other checks from JsonExtensions.IsNullOrEmpty()
        // from https://stackoverflow.com/questions/24066400/checking-for-empty-null-jtoken-in-a-jobject
        return rootNode.DescendantsAndSelf()
            .OfType<JValue>()
            .Any(n => n.Type == JTokenType.Null);
    }

    public static IEnumerable<JToken> DescendantsAndSelf(this JToken rootNode)
    {
        if (rootNode == null)
            return Enumerable.Empty<JToken>();
        var container = rootNode as JContainer;
        if (container != null)
            return container.DescendantsAndSelf();
        else
            return new[] { rootNode };
    }
}

然后做:

var root = JToken.Parse(jsonString);
var anyNull = root.AnyNull();

如果您只想检查null 属性值(即数组中的空值是否正常),您可以使用以下扩展方法:

public static partial class JsonExtensions
{
    public static bool AnyNullPropertyValues(this JToken rootNode)
    {
        if (rootNode == null)
            return true;
        return rootNode.DescendantsAndSelf()
            .OfType<JProperty>()
            .Any(p => p.Value == null || p.Value.Type == JTokenType.Null);
    }
}

(你的问题并不完全清楚。)

示例JContainer.DescendantsAndSelf()