2017-10-20 97 views
2

我從外部API獲取大嵌套JSON對象。我想確保所有字段都填充在該json對象中。有沒有任何libray可以做到這一點? Newtonsoft.JsonJToken類,它檢查Json的模式是否有效,但是我沒有找到任何方法來檢查json對象中的所有字段是否都被填充。如何檢查Json對象是否填充了所有值

場景:我正在構建一個收集關於某個人或實體的信息的api。有許多信息來源。我需要繼續搜索數據,直到所需的對象已滿。所以首先調用api1,獲取一些數據,檢查對象是否已滿。如果對象未滿,則轉到api2等。所以調用在對象滿了之後返回。 一個關鍵點是所需的對象模式不是靜態的。

我可以將它反序列化爲一個POCO並遍歷每個嵌套對象,但我正在尋找更好的解決方案。

任何建議,非常感謝。

+1

您可以使用[Json.NET需要反序列化的所有屬性](https://stackoverflow.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

回答

2

如果你有一個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://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(); 

如果你只是想檢查空屬性值(即數組中的空值都可以)您可以使用以下擴展方法:

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

2

如果我正確地理解了你,你有一些複雜的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中的數組) –