Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to validate json with avro schema in nodejs which can return list of errors for which data errors occured

Below is the code snippet for validating json for an avro schema in nodejs using avro-js module.

//import module
var avro = require('avro-js');
// path to avro schema
var type2 = avro.parse('./Person.avsc');
// sample payload
var person = {name: 'Bob', address: {city: 'Cambridge', zip: '02139'}};
// validate command
var status = type2.isValid(person); // Boolean status.

--- File person.avsc

{
  "name": "Person",
  "type": "record",
  "fields": [
    {"name": "name", "type": "string"},
    {"name": "age", "type": ["null", "int"], "default": null},
    {
      "name": "gender",
      "type": {"name": "Gender", "type": "enum", "symbols": ["FEMALE", "MALE"]}
    },
    {
      "name": "address",
      "type": {
        "name": "Address",
        "type": "record",
        "fields": [{"name": "zipcode", "type": "int"}]
      }
    }
  ]
}

In above snippet I get whether the input payload is valid or not what I want is which elements is causing this schema validtion error like errorList returned after validation.

Please let me know

like image 848
user3715855 Avatar asked Sep 17 '25 00:09

user3715855


1 Answers

It seems the isValid function accepts a set of options as the optional 2nd argument. Inside those options is an errorHook handler you can create. When avro-js invokes that errorHook it will pass in three params (path, any, type), which you can use to construct a richer error message (specifically the path param).

//import module
const avro = require('avro-js')
// path to avro schema
const type2 = avro.parse('./Person.avsc')
// sample payload
const person = {name: 'Bob', address: {city: 'Cambridge', zip: '02139'}}
// validate command
const status = type2.isValid(person, {
  errorHook(path, any, type) {
    console.error(`'${any}' is not a valid value (of type ${type}) for '${path.join(".")}'`)
  }
})

// 'undefined' is not a valid value (of type "Gender") for 'gender'
// 'undefined' is not a valid value (of type "int") for 'address.zipcode'

You can still use the returned value of isValid (which here is false) to drive your logic. Or if you're more used to other schema based validators in JavaScript (like Joi, Spected, or Yup), you can instead customize your errorHook to place those validation errors onto an object in the outer scope:

const has = (key, obj) => Object.prototype.hasOwnProperty.call(obj, key)
const validationErrors = {}

type2.isValid(person, {
  errorHook(path, any, type) {
    const dotPath = path.join(".")
    if (!has(dotPath, validationErrors)) {
      validationErrors[dotPath] = []
    }
    validationErrors[dotPath].push(
      `'${any}' is not a valid value of type ${type}`
    )
  }
})

if (Object.keys(validationErrors).length > 0) {
  console.error(validationErrors)
}

// {
//  gender: [ `'undefined' is not a valid value of type "Gender"` ],
//  'address.zipcode': [ `'undefined' is not a valid value of type "int"` ]
// }
like image 110
Developer Dave Avatar answered Sep 18 '25 18:09

Developer Dave