简体   繁体   English

如何根据 Avro 模式验证 JSON

[英]How do I validate JSON against Avro schema

I have a JSON response from an API and I would like to validate against an existing Avro schema(strict validation with names and types).我有一个来自 API 的 JSON 响应,我想根据现有的 Avro 模式进行验证(使用名称和类型进行严格验证)。

The response is of type响应类型

{"name":"alex","age":23,"sex":"M","active":"true"} {"name":"alex","age":23,"sex":"M","active":"true"}

The schema has the above types with the data types and I would like to validate the schema and throw an exception in case it fails.(Preferably JAVA).模式具有上述类型和数据类型,我想验证模式并在失败时抛出异常。(最好是 JAVA)。

I have read a solution using the command line but I wanted to do it programmatically.我已经使用命令行阅读了一个解决方案,但我想以编程方式进行。

Thanks in advance提前致谢

This is how you can validate it programatically.这是您可以通过编程方式验证它的方式。

import org.apache.avro.AvroTypeException;
import org.apache.avro.Schema;
import org.apache.avro.generic.GenericDatumReader;
import org.apache.avro.io.DatumReader;
import org.apache.avro.io.Decoder;
import org.apache.avro.io.DecoderFactory;

import java.io.*;

public class MainClass {
    public static void main (String [] args) throws Exception {
        Schema schema = new Schema.Parser().parse("{\n" +
                "     \"type\": \"record\",\n" +
                "     \"namespace\": \"com.acme\",\n" +
                "     \"name\": \"Test\",\n" +
                "     \"fields\": [\n" +
                "       { \"name\": \"name\", \"type\": \"string\" },\n" +
                "       { \"name\": \"age\", \"type\": \"int\" },\n" +
                "       { \"name\": \"sex\", \"type\": \"string\" },\n" +
                "       { \"name\": \"active\", \"type\": \"boolean\" }\n" +
                "     ]\n" +
                "}");
        String json = "{\"name\":\"alex\",\"age\":23,\"sex\":\"M\",\"active\":true}";
        System.out.println(validateJson(json, schema));
        String invalidJson = "{\"name\":\"alex\",\"age\":23,\"sex\":\"M\"}"; // missing active field
        System.out.println(validateJson(invalidJson, schema));
    }

    public static boolean validateJson(String json, Schema schema) throws Exception {
        InputStream input = new ByteArrayInputStream(json.getBytes());
        DataInputStream din = new DataInputStream(input);

        try {
            DatumReader reader = new GenericDatumReader(schema);
            Decoder decoder = DecoderFactory.get().jsonDecoder(schema, din);
            reader.read(null, decoder);
            return true;
        } catch (AvroTypeException e) {
            System.out.println(e.getMessage());
            return false;
        }
    }
}

NOTE: If you are on a java project and facing above error during validation of json.注意:如果您在 Java 项目中并在 json 验证期间遇到上述错误。

In our project we expect a very long JSON object with multiple optional fields, so it was hard to find where is it failing.在我们的项目中,我们期望一个非常长的 JSON 对象具有多个可选字段,因此很难找到它失败的地方。

Tried different ways using SpecificDatumReader/GenericDatumReaders and other probable ways, but I was always ending up with Expected start-union.使用SpecificDatumReader/GenericDatumReaders 和其他可能的方法尝试了不同的方法,但我总是以Expected start-union 结束。 Got VALUE_STRING获得了 VALUE_STRING

We have a SpringBoot application and we were already converting the avsc files to Java.我们有一个 SpringBoot 应用程序,我们已经将 avsc 文件转换为 Java。 So the idea was if we are able to populate the Class object and able to serialize it successfully, it shows that JSON received is valid.因此,我们的想法是,如果我们能够填充 Class 对象并成功对其进行序列化,则表明接收到的 JSON 是有效的。

So we ended up using a basic ObjectMapper to populate the class.所以我们最终使用了一个基本的 ObjectMapper 来填充这个类。 And if you are compiling avsc files to Java using avro library, then it comes with some default methods to encode/decode the class如果您使用 avro 库将 avsc 文件编译为 Java,那么它带有一些默认方法来编码/解码类

ObjectMapper mapper = new ObjectMapper();
// DeSerializing the JSON to Avro class, but this doesn't check for Schema restrictions
StatusUpdated obj = mapper.readValue(payload, StatusUpdated.class);
// Encoding the class and serializing to raw format, this step validates based on schema
obj.toByteBuffer();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM