Back to Home

Simple JSON Schema validator for Objective-C

objective-c · json · json-schema · validator · binding · iOS

Simple JSON Schema validator for Objective-C

    Or a tale about how the development of JSON validator turned into another JSON binding


    While normal developers write applications, I invent bicycles.

    Probably many developers have come across a situation where a mobile application is being developed in parallel with the backend. At the same time, often the data structures that come in response to a request from the server can change. For example, on the backend side, they decide to change the name of one of the JSON keys, forgetting to warn the mobile team about this. I'm not talking about situations where CamelCase decided to “suddenly” change the notation to underscore or vice versa. You can say that there is a poor organization of the process and a lack of communication between the teams, and you will be absolutely right. But when the application on the customer’s smartphone stops working on the demo, all eyes are on the mobile phone.


    One of the solutions is the validation of the sent JSON in accordance with the JSON scheme (an overview article on JSON schemes ).

    For example, if the JSON sent to us
    {
        "numberKey" : 100500,
        "arrayKey" : [
        {
            "number" : 1 ,
            "string" : "1"
        },
        {
            "number" : 2 ,
            "string" : "2"
        },
        {
            "number" : 3 ,
            "string" : "3"
        }
        ]
    }
    

    The minimum JSON schema that describes it will be
    {
        "type" : "object",
        "properties" : {
            "numberKey" : {
                "type" : "number"
            },
            "arrayKey" : {
                "type" : "array",
                "items" : {
                    "type" : "object",
                    "properties" : {
                        "number" : {
                            "type" : "number"
                        },
                        "string" : {
                            "type" : "string"
                        }
                    }
                }
            }
        }
    }
    

    All that we ideally need is to take the sent JSON and validate it using the circuit. It would seem that the problem has been resolved. JSON-schema is a standard way to describe JSON, and there are validators for many programming languages. But the search for a validator for the Objective-C language did not give any sane result, so it was decided to follow the path of bicycle construction.

    As a result, a piece called JsonSchemaValidator (bitbucket) was born. For those who want to try:
    pod 'SVJsonSchemaValidator'
    

    So, with the help of this library, we can make a diagram:
    id schema = [[SVType object] properties: @ {
                           @ "numberKey": [SVType number],
                           @ "arrayKey": [[SVType array] items: [[SVType object] properties: @ {
                                                                                    @ "number": [SVType number],
                                                                                    @ "string": [SVType string]
                                                                                }]]
                 }];

    As you can see, the almost one-to-one scheme repeats JSON itself. Now validate it:
    NSError * error = nil;
    id validatedJson = [schema validateJson: json error: & error];
    Here are the variables:
    json is the JSON parsed by any parser (for example, using NSJSONSerialization).
    validatedJson - only those objects that have passed validation.
    error - a more or less sane description of which objects failed to validate. nil - if everything is OK.

    Suppose you already have a model class
    @interface MyModelObject: NSObject
     
    @property (strong, nonatomic) NSString * string;
    @property (strong, nonatomic) NSNumber * number;
     
    @end

    I don’t want to do double work and describe existing classes in the diagram. You can create a schema directly from this class:
    id schema = [[SVType object] properties: @ {
                           @ "numberKey": [SVType number],
                           @ "arrayKey": [[SVType array] items: [MyModelObject jsonSchema]]
                       }];

    Using objc-runtime, the -jsonSchema method for the MyModelObject class will go through all the properties that can be represented in JSON and generate exactly the same scheme. Using the same scheme, you can instantiate objects of type MyModelObject and fill their properties with the appropriate values ​​through KVC:
    NSDictionary * instanciated = [schema instantiateValidatedJson: validated];

    (lldb) po instanciated
    $ 1 = 0x0755fe70 {
        numberKey = 100500,
        arrayKey = (
            "",
            "",
            "",
            ""
        );
    }

    That's all that is implemented at the moment.
    And now the question, for which this short topic was written: does anyone need this bike, and if so, what else is required of it? Waiting for answers in kamenty.

    Read Next