.Net使用JsonSchema驗證Json


  

  最近項目中遇到了這樣的需求,需要對上傳的Json進行驗證,以確保Json數據的准確性。前后使用了兩種方式來驗證:

 

  (1)第一種方式的實現思想:根據Json數據的格式,嚴格定義相應的類結構,並在System.Runtime.Serialization命名空間下的DataContractAttribute、DataMemberAttribute對class和property進行標注,如果property是必須提供的,則在Property上添加[DataMember(IsRequired = true)]。

  然后使用Newtonsoft.Json程序集中的JsonConvert.DeserializeObject<T>()方法加需要驗證的JsonContent反序列化一下,並用try...catch包含反序列化語句,如果轉換成功,則表明JsonContent格式滿足要求。如果轉換不成功,則會拋出異常,有catch接住。

  

  

            try
            {
                var obj = JsonConvert.DeserializeObject<SkuConfigEntity>(skuManifest, new JsonSerializerSettings()
                {
                    Formatting = Formatting.Indented,
                    NullValueHandling = NullValueHandling.Ignore,
                    MissingMemberHandling = MissingMemberHandling.Error
                });
            }
            catch(Exception e)
            {
                return false;
            }

  

這種方法是最初使用的方法,個人認為不完善,也不夠完美,轉換出錯的情況加,exception中不能給出具體的出錯原因。

 

  (2)第二種實現思想:Json Schema(Json 模式)。在前輩的指點下,我知道了Json Schema,

 JSON 模式是一種基於 JSON 格式定義 JSON 數據結構的規范。它被寫在 IETF 草案下並於 2011 年到期。JSON 模式:

  • 描述現有數據格式。
  • 干凈的人類和機器可讀的文檔。
  • 完整的結構驗證,有利於自動化測試。
  • 完整的結構驗證,可用於驗證客戶端提交的數據。

JSON 模式驗證庫

目前有好幾個驗證器可用於不同的編程語言。但是目前最完整和兼容 JSON 模式的驗證器是 JSV。

語言 程序庫
C WJElement (LGPLv3)
Java json-schema-validator (LGPLv3)
.NET Json.NET (MIT)
ActionScript 3 Frigga (MIT)
Haskell aeson-schema (MIT)
Python Jsonschema
Ruby autoparse (ASL 2.0); ruby-jsonschema (MIT)
PHP php-json-schema (MIT). json-schema (Berkeley)
JavaScript Orderly (BSD); JSV; json-schema; Matic (MIT); Dojo; Persevere (modified BSD or AFL 2.0); schema.js.

   

 

 

 

 

 

 

 

 

 

JSON 模式示例

下面是一個基本的 JSON 模式,其中涵蓋了一個經典的產品目錄說明:

{
    "$schema": "http://json-schema.org/draft-04/schema#",
    "title": "Product",
    "description": "A product from Acme's catalog",
    "type": "object",
    "properties": {
        "id": {
            "description": "The unique identifier for a product",
            "type": "integer"
        },
        "name": {
            "description": "Name of the product",
            "type": "string"
        },
        "price": {
            "type": "number",
            "minimum": 0,
            "exclusiveMinimum": true
        }
    },
    "required": ["id", "name", "price"]
}

我們來看一下可以用於這一模式中的各種重要關鍵字:

關鍵字 描述
$schema $schema 關鍵字狀態,表示這個模式與 v4 規范草案書寫一致。
title 用它給我們的模式提供了標題。
description 關於模式的描述。
type type 關鍵字在我們的 JSON 數據上定義了第一個約束:必須是一個 JSON 對象。
properties 定義各種鍵和他們的值類型,以及用於 JSON 文件中的最小值和最大值。
required 存放必要屬性列表。
minimum 給值設置的約束條件,表示可以接受的最小值。
exclusiveMinimum 如果存在 "exclusiveMinimum" 並且具有布爾值 true,如果它嚴格意義上大於 "minimum" 的值則實例有效。
maximum 給值設置的約束條件,表示可以接受的最大值。
exclusiveMaximum 如果存在 "exclusiveMinimum" 並且具有布爾值 true,如果它嚴格意義上小於 "maximum" 的值則實例有效。
multipleOf 如果通過這個關鍵字的值分割實例的結果是一個數字則表示緊靠 "multipleOf" 的數字實例是有效的。
maxLength 字符串實例字符的最大長度數值。
minLength 字符串實例字符的最小長度數值。
pattern 如果正則表達式匹配實例成功則字符串實例被認為是有效的。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

上述的Json模式可以驗證如下Json串。

[
    {
        "id": 2,
        "name": "An ice sculpture",
        "price": 12.50
    },
    {
        "id": 3,
        "name": "A blue mouse",
        "price": 25.50
    }
]


在.Net中,Json Schema 通過Newtonsoft.Json.Schema命名空間下的JsonSchema類可以實現。

每一個JsonSchema實例表示對一個Property的描述以及限制。

    JsonSchema class的幾個關鍵屬性:

Type 設置Property的類型  
Required 設置Property是否為必須的  
Properties 包含的所有下一級Property的JsonSchema,該屬性是Dictionary<string,JsonSchema>類型,添加子項之前需初始化。  
Items 包含的所有下一級的數組項的JsonSchema,該屬性是IList<JsonSchema>類型,添加子項之前需要初始化。  
     
     
     

 

 

 

 

 

 

 

 

使用Newtonsoft.Json.Schema命名空間下的IsValid()擴展方法,可實現對Json串的驗證,該方法是JToken的擴展方法。

 

    public static JsonSchema GetSkuJsonSchema()
    {

                JsonSchema rootSchema = new JsonSchema() { Title = "Sku.Json", Type = JsonSchemaType.Object };

            rootSchema.Properties = new Dictionary<string, JsonSchema>();
            rootSchema.Properties.Add("name", new JsonSchema() { Type = JsonSchemaType.String, Required = true });
            rootSchema.Properties.Add("displayName", new JsonSchema() { Type = JsonSchemaType.String, Required = true });
            rootSchema.Properties.Add("apimInstance", new JsonSchema() { Type = JsonSchemaType.String, Required = true });
            rootSchema.Properties.Add("apiPath", new JsonSchema() { Type = JsonSchemaType.String, Required = true });

            JsonSchema skuSchema = new JsonSchema() { Title = "skus", Type = JsonSchemaType.Array, Required = true };
            skuSchema.Properties= new Dictionary<string, JsonSchema>();
            skuSchema.Properties.Add("name", new JsonSchema() { Type = JsonSchemaType.String, Required = true });
            skuSchema.Properties.Add("tier", new JsonSchema() { Type = JsonSchemaType.String, Required = true });
            skuSchema.Properties.Add("subscriptionSkuQuota", new JsonSchema() { Type = JsonSchemaType.Integer, Required = false });
            skuSchema.Properties.Add("skutype", new JsonSchema() { Type = JsonSchemaType.String, Required = false });
            skuSchema.Properties.Add("skuquota", new JsonSchema() { Type = JsonSchemaType.String, Required = false });
            skuSchema.Properties.Add("apimProductId", new JsonSchema() { Type = JsonSchemaType.String, Required = false });

            JsonSchema locationsSchema = new JsonSchema() { Title = "locations", Type = JsonSchemaType.Array, Required = true };
            locationsSchema.Properties= new Dictionary<string, JsonSchema>();
            locationsSchema.Properties.Add("location", new JsonSchema() { Type = JsonSchemaType.String, Required = true });
            locationsSchema.Properties.Add("apimProductId", new JsonSchema() { Type = JsonSchemaType.String, Required = false });
            skuSchema.Properties.Add("locations", locationsSchema);

            JsonSchema meterIdsSchema = new JsonSchema() { Title = "meterIds", Type = JsonSchemaType.Array, Required = true };
            meterIdsSchema.Items = new List<JsonSchema>();
            meterIdsSchema.Items.Add(new JsonSchema() { Type = JsonSchemaType.String, Required = false });
            skuSchema.Properties.Add("meterIds", meterIdsSchema);

            JsonSchema requiredFeaturesSchema = new JsonSchema() { Title = "requiredFeatures", Type = JsonSchemaType.Array, Required = true };
            requiredFeaturesSchema.Items = new List<JsonSchema>();
            requiredFeaturesSchema.Items.Add(new JsonSchema() { Type = JsonSchemaType.String, Required = false });
            skuSchema.Properties.Add("requiredFeatures", requiredFeaturesSchema);

            rootSchema.Properties.Add("skus", skuSchema);

            return rootSchema;
  }

  

JToken jtoken=JToken.Parse(jsonContent);

IList<string> errorList;

var result=jtoken.IsValid(schema, out errorList);

如果驗證成功,則返回ture,如果驗證失敗,則返回false,並且errorList中會包含詳細的錯誤信息。

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM