BeniaminoBaggins
BeniaminoBaggins

Reputation: 12503

Json.NET validate JSON array against Schema

I want to validate a schema which has an array, all in one call to the validate method. I did it in javascript but I am sturggling to do it in C# with Json.NET. With Json.NET I am calling the validation method for each object in the array like so:

JSchema schema = JSchema.Parse(@"{
                'title': 'HouseCollection',
    'description': '',
    '$schema': 'http://json-schema.org/draft-04/schema#',
    'definitions': {
                    'Categories': {
                        'title': 'Categories',
            'description': '',
            '$schema': 'http://json-schema.org/draft-04/schema#',
            'type': 'object',
            'additionalProperties': false,
            'properties': {
                            'serviceCode': {
                                'description': 'xxx,
                    'type': 'string'
                            }
                        },
            'required': [
                'serviceCode'
            ]
    },
        'House': {
            'title': 'House',
            'description': '',
            '$schema': 'http://json-schema.org/draft-04/schema#',
            'type': 'object',
            'additionalProperties': false,
            'properties': {
                'aaa': {
                    'type': 'string'
                },
                'bbb': {
                    'type': 'string'
                },
                'ccc': {
                    'description': 'xxx',
                    'type': 'string'
                },
                'ddd': {
                    'type': 'number'
                },
                'eee': {
                    'description': 'xxx',
                    'type': 'boolean'
                },
                'fff': {
                    'description': 'xxx',
                    'type': 'string'
                },
                'ggg': {
                    'description': 'xxx',
                    'type': 'string'
                },
                'hhh': {
                    'type': 'number'
                },
                'iii': {
                    'description': 'xxx',
                    'type': 'string'
                },
                'jjj': {
                    'type': 'string'
                },
                'kkk': {
                    'description': 'xxx',
                    'type': 'string'
                },
                'lll': {
                    'description': 'xxx',
                    'type': 'string'
                },
                'mmm': {
                    'description': '',
                    'type': 'string'
                },
                'nnn': {
                    'description': '',
                    'type': 'array',
                    'items': {
                        '$ref': '#/definitions/Categories'
                    }
                }
            },
            'required': [
                'HouseName'
            ]
        },
        'HouseCollection': {
            '$ref': '#'
        }
    },
    'type': 'object',
    'additionalProperties': false,
    'properties': {
        'houses': {
            'description': '',
            'type': 'array',
            'items': {
                '$ref': '#/definitions/House'
            }
        }
    }
}");

            string housesJsonString = JsonConvert.SerializeObject(houses);
             bool valid = false;
            JArray housesJson = JArray.Parse(housesJsonString);

            foreach (JObject s in housesJson)
            {
                IList<string> messages;
                valid = housesJson.IsValid(schema, out messages);
            }


            return valid;

How do I alter this code to call the validation method once? When I tried it it gave this error in the messages IList:

Invalid type. Expected Object but got Array. Path ", line1, position 1."

Upvotes: 3

Views: 3059

Answers (2)

KR Akhil
KR Akhil

Reputation: 1017

Modifying the foreach in your code worked for me. Posting the entire method below.

Invalid type. Expected Object but got Array. Path ", line1, position 1."

    /// <summary>
    /// This method will validate JSON schema using JSON Schema string value
    /// </summary>
    /// <param name="responseJSONValue">Response received in JSON format or a JSON value for which schema validation is to be performed</param>
    /// <param name="expectedJSONSchema">Expected JSON schema as string which need to validate against JSON value</param>
    /// <param name="messages">This will return error messages in List if validation fails</param>
    /// <returns>This method will return True or False as per JSON schema validation result</returns>
    public bool IsJSONSchemaValid(string responseJSONValue, string expectedJSONSchema, out IList<string> messages)
    {
        try
        {
            bool isSchemaValid = false;
            messages = null;
            JSchema schema = JSchema.Parse(expectedJSONSchema);

            //For JSON object - schema validation
            if (responseJSONValue.StartsWith("{") && responseJSONValue.EndsWith("}"))
            {
                JObject jObject = JObject.Parse(responseJSONValue);
                isSchemaValid = jObject.IsValid(schema, out messages);
            }

            //For JSON array - schema validation
            if (responseJSONValue.StartsWith("[") && responseJSONValue.EndsWith("]"))
            {
                JArray jArray = JArray.Parse(responseJSONValue);

                foreach (JObject currentObject in jArray)
                {
                    isSchemaValid = currentObject.IsValid(schema, out messages);

                    if (!isSchemaValid)
                    {
                        break;
                    }
                }
            }

            return isSchemaValid;
        }
        catch (Exception)
        {
            throw;
        }
    }

Upvotes: 0

BeniaminoBaggins
BeniaminoBaggins

Reputation: 12503

Creating an object and placing the array inside it was the solution.

var housesObject = new {
 houses = houses
};

string housesJsonString = JsonConvert.SerializeObject(housesObject);
JObject housesJson = JObject.Parse(housesJsonString);
IList < string > messages;
bool valid = housesJson.IsValid(schema, out messages);
return valid;

Upvotes: 1

Related Questions