web-dev-qa-db-ja.com

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"}
       ]}
    }
  ]
}
8
derdc

4つの可能な方法があります:

  1. これに記載されているようにpomファイルに含める ticket
  2. すべてのタイプを単一のavscファイルで宣言します。
  3. 最初にすべてのインポートを解析し、次に実際のデータ型を解析する単一の静的パーサーを使用します。
  4. (これはハックです)avdlファイルを使用し、 https://avro.Apache.org/docs/1.7.7/idl.html#imports のようなインポートを使用します。ただし、IDLはRPC呼び出しを対象としています。

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

スキーマを保持したい場合、つまり新しいレコードを作成したい場合は、次のいずれかを実行できます 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>); 
18
Princey James

その他@PrinceyJamesに追加

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

    }
  }
0
raphaelauv

@Princey Jamesの回答に追加するには、ネストされた型を使用する前に定義する必要があります。

0
Ming