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

问题描述:

我从外部API获取大嵌套JSON对象。我想确保所有字段都填充在该json对象中。有没有任何libray可以做到这一点? Newtonsoft.JsonJToken类,它检查Json的模式是否有效,但是我没有找到任何方法来检查json对象中的所有字段是否都被填充。如何检查Json对象是否填充了所有值

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

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

任何建议,非常感谢。

+1

您可以使用[Json.NET需要反序列化的所有属性](https://*.com/a/29660550/3744182)中的RequireObjectPropertiesContractResolver。从你的问题来看,你是否想[[Required.Always'或'Required.AllowNull'](https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_Required.htm)还不清楚。 – dbc

+0

我需要'Required.Always'。所以它在反序列化时检查?它也适用于儿童吗? – Venky

+0

反正有没有反序列化json来达到相同的结果? – Venky

如果你有一个JSON字符串,只是想检查任何属性值或数组项目是否null,你可以解析到JToken递归下降JToken层次结构与JContainer.DescendantsAndSelf(),并检查每个JValuenull使用以下扩展方法:

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://*.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(); 

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

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); 
    } 
} 

(从您的问题中不完全清楚您想要什么。)

样品.Net fiddle

+0

@BrianRogers - 好主意,完成。 – dbc

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

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

  1. 你已经提到过JSON模式验证。以下是其中一个实现:Json.NET Schema
  2. 创建POCO对象并用相应的必需/不需要属性标记所有属性。在这种情况下,如果json字符串不包含任何强制性数据,您将会收到异常。例如,它是如何在方面做的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) { } 
    

提供的代码样本是由你提到Newtonsoft.Json

+0

谢谢伊霍尔。但响应json对象不是静态的。它变化并且该对象内的所有属性都是必需的。所以如果我传递一个随机json对象,它应该返回我,如果所有的属性被填充或不。 – Venky

+0

@Venky,dbc提出了我的第三个变体的增强版本,它应该适合你的问题。请记住,如果你还需要验证空数组,你必须在'AnyNull()'方法中再添加一个检查(用JArray对象表示的Json.net中的数组) –