0

I have a web call that returns JSON.

The response call can either be an array or an object.

I want to validate if the response is the array.

I am using JSON.NET.

Here is my schema:

    string planElevationListSchema = @"{
        'description': 'Plan elevation object array',
        'type': 'array',
        'items': {
            'type': 'object',
            'properties': {
                'COMMUNITYNUMBER': { 'type': 'string' },
                'PLANNUMBER': { 'type': 'string' },
                'ELEVATION': { 'type': 'string' }
            }
        }
    }";

Here is my code:

JsonSchema schema = JsonSchema.Parse(planElevationListSchema);

JArray planElevationList = JArray.Parse(responseFromServer.ToString());

bool isValid = planElevationList.IsValid(schema);

If the JSON object is returned, I get an

"Error reading JArray from JsonReader. Current JsonReader item is not an array: StartObject. Path '', line 1, position 1."

Do I need to wrap my code in a try/catch or make another schema for the object?

Whichever I use to parse the response could throw an exception.

How to handle?

Added Here is what the returned object looks like:

"{ \"Error\": \"No Active Plan/Elevations for 44003150099\" }"

Here is the valid object array returned:

"[{\"COMMUNITYNUMBER\":\"44002050000\",\"PLANNUMBER\":\"1700\",\"ELEVATION\":\"A\"},{\"COMMUNITYNUMBER\":\"44002050000\",\"PLANNUMBER\":\"1700\",\"ELEVATION\":\"B\"},{\"COMMUNITYNUMBER\":\"44002050000\",\"PLANNUMBER\":\"1700\",\"ELEVATION\":\"C\"},{\"COMMUNITYNUMBER\":\"44002050000\",\"PLANNUMBER\":\"1700\",\"ELEVATION\":\"D\"},{\"COMMUNITYNUMBER\":\"44002050000\",\"PLANNUMBER\":\"1800\",\"ELEVATION\":\"A\"},{\"COMMUNITYNUMBER\":\"44002050000\",\"PLANNUMBER\":\"1800\",\"ELEVATION\":\"B\"},{\"COMMUNITYNUMBER\":\"44002050000\",\"PLANNUMBER\":\"1800\",\"ELEVATION\":\"C\"},{\"COMMUNITYNUMBER\":\"44002050000\",\"PLANNUMBER\":\"1800\",\"ELEVATION\":\"D\"},{\"COMMUNITYNUMBER\":\"44002050000\",\"PLANNUMBER\":\"1890\",\"ELEVATION\":\"A\"},{\"COMMUNITYNUMBER\":\"44002050000\",\"PLANNUMBER\":\"1890\",\"ELEVATION\":\"B\"},{\"COMMUNITYNUMBER\":\"44002050000\",\"PLANNUMBER\":\"1890\",\"ELEVATION\":\"C\"},{\"COMMUNITYNUMBER\":\"44002050000\",\"PLANNUMBER\":\"1890\",\"ELEVATION\":\"D\"},{\"COMMUNITYNUMBER\":\"44002050000\",\"PLANNUMBER\":\"2270\",\"ELEVATION\":\"A\"},{\"COMMUNITYNUMBER\":\"44002050000\",\"PLANNUMBER\":\"2270\",\"ELEVATION\":\"B\"},{\"COMMUNITYNUMBER\":\"44002050000\",\"PLANNUMBER\":\"2270\",\"ELEVATION\":\"C\"},{\"COMMUNITYNUMBER\":\"44002050000\",\"PLANNUMBER\":\"2270\",\"ELEVATION\":\"D\"},{\"COMMUNITYNUMBER\":\"44002050000\",\"PLANNUMBER\":\"2440\",\"ELEVATION\":\"A\"},{\"COMMUNITYNUMBER\":\"44002050000\",\"PLANNUMBER\":\"2440\",\"ELEVATION\":\"B\"},{\"COMMUNITYNUMBER\":\"44002050000\",\"PLANNUMBER\":\"2440\",\"ELEVATION\":\"C\"},{\"COMMUNITYNUMBER\":\"44002050000\",\"PLANNUMBER\":\"2440\",\"ELEVATION\":\"D\"}]"

DaveB
  • 9,470
  • 4
  • 39
  • 66
  • How does the schema apply when the received JSON root object is an object and the schema specifies an array? Should the received root object be validated as if it were an item in the array? – dbc Feb 12 '18 at 23:17
  • Also, are you really using `JsonSchema`? I ask because, according to the [docs](https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_Schema_JsonSchema.htm), ***Note: This API is now obsolete.** JSON Schema validation has been moved to its own package. See http://www.newtonsoft.com/jsonschema for more details.* – dbc Feb 12 '18 at 23:23
  • I am on version 6 of JSON.NET so I may not be using the latest and greatest. – DaveB Feb 12 '18 at 23:28
  • @dbc I don't know what you are asking. I would like to know if the returned JSON is the array or object. Thanks! – DaveB Feb 12 '18 at 23:32
  • What I mean is as follows. Say your received JSON has an object as its root value. You have a schema that specifies that the root token must be an array. How do you want to validate the received object against the schema? As if you have received an array containing it as a single item? – dbc Feb 12 '18 at 23:34
  • @dbc - I would like to validate that the returned JSON is an array of objects as I have laid out in my schema at its root value. If it's an object and not an array, then I would think that IsValid would return false but it seems that you need to either use JObject or JArray which kind of locks you in. But then this is my first use of this and I may be missing something! – DaveB Feb 12 '18 at 23:43

2 Answers2

0

You can use JToken.Parse() to parse any arbitrary well-formed JSON:

var schema = JsonSchema.Parse(planElevationListSchema); 

var planElevations = JToken.Parse(responseFromServer.ToString());
var isValid = planElevations.IsValid(schema);

You can also check the actual JToken.Type for subsequent processing, e.g.:

var isValid = (schema.Type == JsonSchemaType.Array && planElevations.Type != JTokenType.Array // Quick reject
               ? false : planElevations.IsValid(schema));

Sample working .Net fiddle. See also JSON.NET: Why Use JToken--ever? which describes additional situations in which one might want to use the abstract base class JToken.

dbc
  • 104,963
  • 20
  • 228
  • 340
  • What is the purpose of the line that checks if `planElevations` is a `JArray` then either casts it as a `JArray` or a new `JArray` even if it's not a `JArray`? – DaveB Feb 13 '18 at 19:29
  • @DaveB - in the original version of your question, I thought your problem was that the server would return a single item in preference to an array of one item, as is shown in [How to handle both a single item and an array for the same property using JSON.net](https://stackoverflow.com/q/18994685/3744182). It's a weirdly common thing to do. But now I see it's a completely different object, so I can edit that out of the question. – dbc Feb 13 '18 at 19:32
-1

Change the ' to ". See below:

{
  "description": "Plan elevation object array",
  "type": "array",
  "items": {
    "type": "object",
    "properties": {
      "COMMUNITYNUMBER": {
        "type": "string"
      },
      "PLANNUMBER": {
        "type": "string"
      },
      "ELEVATION": {
        "type": "string"
      }
    }
  }
}
H77
  • 5,859
  • 2
  • 26
  • 39
AdamB
  • 1