Avro架构定义嵌套类型

时间:2015-03-26 14:08:51

标签: avro

我对Avro相当新,并浏览了嵌套类型的文档。我在下面的示例中运行良好,但模型中的许多不同类型将具有地址。是否可以定义一个address.avsc文件并将其作为嵌套类型引用?如果可以,您是否还可以更进一步,为客户提供地址列表?提前谢谢。

{"namespace": "com.company.model",
  "type": "record",
  "name": "Customer",
  "fields": [
    {"name": "firstname", "type": "string"},
    {"name": "lastname", "type": "string"},
    {"name": "email", "type": "string"},
    {"name": "phone", "type": "string"},
    {"name": "address", "type":
      {"type": "record",
       "name": "AddressRecord",
       "fields": [
         {"name": "streetaddress", "type": "string"},
         {"name": "city", "type": "string"},
         {"name": "state", "type": "string"},
         {"name": "zip", "type": "string"}
       ]}
    }
  ]
}

3 个答案:

答案 0 :(得分:17)

有四种可能的方式:

  1. 将其包含在此ticket中提到的pom文件中。
  2. 在一个avsc文件中声明所有类型。
  3. 使用单个静态解析器,首先解析所有导入,然后解析实际数据类型。
  4. (这是一个黑客)使用avdl文件并使用https://avro.apache.org/docs/1.7.7/idl.html#imports之类的导入。但是,IDL用于RPC调用。
  5. 2的示例。在一个avsc文件中声明所有类型。还在地址上回答数组声明。

    [
    {
        "type": "record",
        "namespace": "com.company.model",
        "name": "AddressRecord",
        "fields": [
            {
                "name": "streetaddress",
                "type": "string"
            },
            {
                "name": "city",
                "type": "string"
            },
            {
                "name": "state",
                "type": "string"
            },
            {
                "name": "zip",
                "type": "string"
            }
        ]
    },
    {
        "namespace": "com.company.model",
        "type": "record",
        "name": "Customer",
        "fields": [
            {
                "name": "firstname",
                "type": "string"
            },
            {
                "name": "lastname",
                "type": "string"
            },
            {
                "name": "email",
                "type": "string"
            },
            {
                "name": "phone",
                "type": "string"
            },
            {
                "name": "address",
                "type": {
                    "type": "array",
                    "items": "com.company.model.AddressRecord"
                }
            }
        ]
    },
    {
        "namespace": "com.company.model",
        "type": "record",
        "name": "Customer2",
        "fields": [
            {
                "name": "x",
                "type": "string"
            },
            {
                "name": "y",
                "type": "string"
            },
            {
                "name": "address",
                "type": {
                    "type": "array",
                    "items": "com.company.model.AddressRecord"
                }
            }
        ]
    }
    ]
    

    3的示例。使用单个静态解析器

    Parser parser = new Parser(); // Make this static and reuse
    parser.parse(<location of address.avsc file>);
    parser.parse(<location of customer.avsc file>);
    parser.parse(<location of customer2.avsc file>);
    

    如果我们想要保留Schema,那就是如果我们想要创建新记录,我们可以做到 获取架构的https://avro.apache.org/docs/1.5.4/api/java/org/apache/avro/Schema.Parser.html#getTypes()方法 或

    Parser parser = new Parser(); // Make this static and reuse
    Schema addressSchema =parser.parse(<location of address.avsc file>);
    Schema customerSchema=parser.parse(<location of customer.avsc file>);
    Schema customer2Schema =parser.parse(<location of customer2.avsc file>); 
    

答案 1 :(得分:0)

只需将嵌套类型添加到@Princey James答案中,就必须先定义该嵌套类型。

答案 2 :(得分:0)

其他添加到@Princey James

示例2为例。在单个avsc文件中声明所有类型。

它将用于通过代码生成对进行序列化和反序列化

但在没有代码生成的情况下对进行序列化和反序列化 不起作用

您将得到org.apache.avro.AvroRuntimeException:不是记录模式:[{“ type”:“ ...

具有代码生成功能的工作示例:

  @Test
  public void avroWithCode() throws IOException {

    UserPerso UserPerso3 = UserPerso.newBuilder()
                                    .setName("Charlie")
                                    .setFavoriteColor("blue")
                                    .setFavoriteNumber(null)
                                    .build();

    AddressRecord adress = AddressRecord.newBuilder()
                                        .setStreetaddress("mo")
                                        .setCity("Paris")
                                        .setState("IDF")
                                        .setZip("75")
                                        .build();

    ArrayList<AddressRecord> li = new ArrayList<>();
    li.add(adress);

    Customer cust = Customer.newBuilder()
                            .setUser(UserPerso3)
                            .setPhone("0101010101")
                            .setAddress(li)
                            .build();

    String fileName = "cust.avro";

    File a = new File(fileName);

    DatumWriter<Customer> customerDatumWriter = new SpecificDatumWriter<>(Customer.class);
    DataFileWriter<Customer> dataFileWriter = new DataFileWriter<>(customerDatumWriter);
    dataFileWriter.create(cust.getSchema(), new File(fileName));
    dataFileWriter.append(cust);
    dataFileWriter.close();

    DatumReader<Customer> custDatumReader = new SpecificDatumReader<>(Customer.class);
    DataFileReader<Customer> dataFileReader = new DataFileReader<>(a, custDatumReader);
    Customer cust2 = null;
    while (dataFileReader.hasNext()) {
      cust2 = dataFileReader.next(cust2);
      System.out.println(cust2);
    }
  }

无:

  @Test
  public void avroWithoutCode() throws IOException {

    Schema schemaUserPerso = new Schema.Parser().parse(new File("src/main/resources/avroTest/user.avsc"));
    Schema schemaAdress = new Schema.Parser().parse(new File("src/main/resources/avroTest/user.avsc"));
    Schema schemaCustomer = new Schema.Parser().parse(new File("src/main/resources/avroTest/user.avsc"));

    System.out.println(schemaUserPerso);

    GenericRecord UserPerso3 = new GenericData.Record(schemaUserPerso);
    UserPerso3.put("name", "Charlie");
    UserPerso3.put("favorite_color", "blue");
    UserPerso3.put("favorite_number", null);

    GenericRecord adress = new GenericData.Record(schemaAdress);

    adress.put("streetaddress", "mo");
    adress.put("city", "Paris");
    adress.put("state", "IDF");
    adress.put("zip", "75");

    ArrayList<GenericRecord> li = new ArrayList<>();
    li.add(adress);

    GenericRecord cust = new GenericData.Record(schemaCustomer);

    cust.put("user", UserPerso3);
    cust.put("phone", "0101010101");
    cust.put("address", li);

    String fileName = "cust.avro";

    File file = new File(fileName);

    DatumWriter<GenericRecord> datumWriter = new GenericDatumWriter<>(schemaCustomer);
    DataFileWriter<GenericRecord> dataFileWriter = new DataFileWriter<>(datumWriter);
    dataFileWriter.create(schemaCustomer, file);
    dataFileWriter.append(cust);
    dataFileWriter.close();

    File a = new File(fileName);

    DatumReader<GenericRecord> datumReader = new GenericDatumReader<>(schemaCustomer);
    DataFileReader<GenericRecord> dataFileReader = new DataFileReader<>(a, datumReader);
    GenericRecord cust2 = null;
    while (dataFileReader.hasNext()) {
      cust2 = dataFileReader.next(cust2);
      System.out.println(cust2);

    }
  }