Hamilton
Hamilton

Reputation: 678

any workaround to easily validate nested JSON response in python?

In flask-restplus, I defined response body data structure using api.model decorator, I am expecting the output of api function should yield exact data structure that I defined. I have lack of ideas how to do it exactly. Can anyone point me out how to validate json response content in flask? any workaround to validate json response output with defined schema? any thoughts?

current output:

here is current output after I made POST request to api function: myfunc:

"{\n\r\n  \"score\": [72.188, 62.0955, 19.3374, 45.6086, 77.8891, 22.188, 45.9938, 91.9877, 14.2527, 1.5408, 62.5578],\n\r\n  \"category\": \"low\",\n\r\n  \"direction\": \"text description\",\n\r\n  \"is_ready\": true,\n\r\n  \"features_used\": {\n\r\n    \"name\": \"heart_rate\",\n\r\n    \"value\": null,\n\r\n    \"range_value\": [3.6667, 5, 6.3333, 7.6667, 9, 10.3333, 11.6667, 13, 14.3333],\n\r\n    \"range_frequency\": [0.0024, 0, 0.0049, 0.0016, 0.0073, 0.0195, 0.0098, 0.0138, 0.9406],\n\r\n    \"level\": 0\n\r\n  }\n\r\n} \n"

question is the format of the current output didn't yield what response body defined. How to fix this? how to validate json response content in flask? any possible way to make this happen? thanks

minimal api with specified response json body

from flask import Flask, jsonify
from flask_restplus import Namespace, Resource, fields, reqparse
from flask_restplus import Api

app = Flask(__name__)
api = Api(app)

ns = api.namespace('hello-world')

used_features = {}
used_features['name'] = fields.String(attribute='name')
used_features['value'] = fields.Integer(attribute='value')
used_features['range_value'] = fields.List(
    fields.Integer, attribute='range_value')
used_features['range_frequency'] = fields.List(
    fields.Integer, attribute='range_frequency')
used_features['level'] = fields.Integer(attribute='level')

used_features_payload = api.model('feature_payload', used_features)

response_body= api.model('response', {
    'score': fields.Integer,
    'category': fields.String,
    'direction': fields.String,
    'is_ready': fields.Boolean,
    'features_used': fields.Nested(used_features_payload)
})

objective:

I want to validate the JSON schema of the current output. How can I validate function output with response body JSON schema? any idea?

Upvotes: 1

Views: 1766

Answers (2)

Jerry07
Jerry07

Reputation: 941

you could validate your response with marshmallow. I figured out your problem as follow:

from marshmallow import Schema, fields, post_load
from marshmallow import EXCLUDE
import json
from flask import jsonify

class Feature:
    def __init__(self, name, value, range_value, range_frequency, importance):
        self.name = name
        self.value = value
        self.range_value = range_value
        self.range_frequency = range_frequency
        self.importance = importance

class FeatureSchema(Schema):
    value = fields.Integer()
    name = fields.Str()
    importance = fields.Integer()
    range_value = fields.List(fields.Integer)
    range_frequency = fields.List(fields.Integer)
    @post_load
    def make_feature(self, data, **kwargs):
        return Feature(**data)

class App(object):
    def __init__(self, score, category, guidance, readiness, features_used):
        self.score = score
        self.category = category
        self.guidance = guidance
        self.readiness = readiness
        self.features_used = features_used

class RespSchema(Schema):
    score = fields.Integer()
    category = fields.Str()
    guidance = fields.Str()
    readiness = fields.Boolean()
    features_used = fields.List(fields.Nested(FeatureSchema))
    @post_load
    def make_app(self, data, **kwargs):
        return App(**data)

marshmallow works pretty good for data validation.

Upvotes: 2

venkata krishnan
venkata krishnan

Reputation: 2046

Ignoring the technical details in your code,

To validate your JSONschema or any defined schema you can use JSONscheme package.

This package is fairly simple to use. Quoting the part of the usage here.

    schema = {
   "type" : "object",
   "properties" : {
    "price" : {"type" : "number"},
    "name" : {"type" : "string"},
     },
 }

you define the schema like this, and you can just pass your object to validate against this schema. if it doesn't match, the validator will throw and exception.

from jsonschema import validate
validate(instance={"name" : "Eggs", "price" : 34.99}, schema=schema)

Upvotes: 0

Related Questions