如何针对Avro架构验证JSON

时间:2018-05-07 17:23:09

标签: java json validation schema avro

我有来自API的JSON响应,我想针对现有的Avro架构进行验证(严格验证名称和类型)。

响应类型为

{ “名称”: “亚历克斯”, “年龄”:23, “性别”: “M”, “活性”: “真”}

模式具有上述类型和数据类型,我想验证模式并在失败时抛出异常。(最好是JAVA)。

我已经使用命令行阅读了解决方案,但我想以编程方式进行。

提前致谢

2 个答案:

答案 0 :(得分:5)

这是您以编程方式验证它的方法。

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;
        }
    }
}

答案 1 :(得分:0)

注意:如果您在 Java 项目中并在 json 验证期间遇到上述错误。

在我们的项目中,我们期望一个非常长的 JSON 对象具有多个可选字段,因此很难找到它失败的地方。

使用SpecificDatumReader/GenericDatumReaders 和其他可能的方法尝试了不同的方法,但我总是以Expected start-union 结束。获得 VALUE_STRING

我们有一个 SpringBoot 应用程序,我们已经将 avsc 文件转换为 Java。因此,我们的想法是,如果我们能够填充 Class 对象并成功对其进行序列化,则表明接收到的 JSON 是有效的。

所以我们最终使用了一个基本的 ObjectMapper 来填充这个类。如果您使用 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();