схема Dynami c с вложенной картой с массивом в avro - получение ClassCastException - PullRequest
0 голосов
/ 11 января 2020

Я пытаюсь сериализовать вложенную карту с массивом.

[
  {
    "valueMap":{
    "num": 3646,
    "pos": {
      "type": "Point",
      "coord": [
        32.234756,
        34.12345
      ]
    }
  },
    "id": "12345",
    "ph": "4546747474"
  }
]

Ниже сгенерированная схема:

{
  "type": "record",
  "name": "test",
  "namespace": "test",
  "doc": "info",
  "fields": [
    {
      "name": "id",
      "type": "string"
    },
    {
      "name": "ph",
      "type": "string"
    },
    {
      "name": "valueMap",
      "type": {
        "type": "array",
        "items": {
          "type": "record",
          "name": "valueMap",
          "namespace": "valueMap",
          "doc": "valueMap",
          "fields": [
            {
              "name": "num",
              "type": {
                "type": "long",
                "logicalType": "num"
              },
              "doc": "num"
            },
            {
              "name": "pos",
              "type": {
                "type": "map",
                "values": {
                  "type": "map",
                  "values": {
                    "type": "record",
                    "name": "pos",
                    "namespace": "pos",
                    "doc": "pos",
                    "fields": [
                      {
                        "name": "type",
                        "type": [
                          "null",
                          "string"
                        ],
                        "doc": "type"
                      },
                      {
                        "name": "coord",
                        "type": [
                          "null",
                          {
                            "type": "array",
                            "items": "double"
                          }
                        ],
                        "doc": "coord"
                      }
                    ]
                  }
                }
              },
              "doc": "pos"
            }
          ]
        }
      },
      "doc": "valueMap_docs_fieldNames"
    }
  ]
}

Вот фрагмент кода, где он не похож на выше схема и ошибка отсутствуют

java .lang.ClassCastException: класс java .lang.String не может быть приведен к классу java .util.Map

DatumWriter<GenericRecord> genericRecordDatumWriter = new GenericDatumWriter<>(schema);

        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        GenericRecord genericRecord = genericRecordT(schema, message);

        try (DataFileWriter<GenericRecord> dataFileWriter = new DataFileWriter<>(genericRecordDatumWriter)) {
            dataFileWriter.create(schema, byteArrayOutputStream);
            dataFileWriter.append(genericRecord);
            dataFileWriter.flush();
        } catch (IOException e) {
            log.error("Could not serialize Generic Record.", e);
            throw new AvroRuntimeException("Could not read schema file.");
        }

        return byteArrayOutputStream.toByteArray();
    }

Ценю любую помощь. Невозможно найти хороший пример.

Спасибо

Код, который я использую

                Schema coordinatesArraySchema = SchemaBuilder.array().items().doubleType();
                //schema for child map 
                Schema xyPosMapSchema = SchemaBuilder.map().values(coordinatesArraySchema);
                xyPosMapSchema.addProp(LOGICAL_TYPE_KEY, "Point");

                //pos fields
                Schema.Field typeF = new Schema.Field("type", Schema.createUnion(Schema.create(Schema.Type.NULL), Schema.create(Schema.Type.STRING)), "type", null);
                Schema.Field coordinateF = new Schema.Field("coordinates", Schema.createUnion(Schema.create(Schema.Type.NULL), coordinatesArraySchema), "coordinates", null);
                List<Schema.Field> xyPosFields = new ArrayList<>();
                xyPosFields.add(typeF);
                xyPosFields.add(coordinateF);
                xyPosMapSchema = Schema.createRecord("xyPos", "xyPos" + "_docs", "xyPos" + "_namespace", false);
                xyPosMapSchema.setFields(xyPosFields);

                //schema for parent map  i.e. measurements
                Schema measurementMapSchema = SchemaBuilder.map().values(xyPosMapSchema);

                measurementFields.add(new Schema.Field(fieldName, Schema.createMap(measurementMapSchema), fieldName, null));
                 Schema measurementSchema = Schema.createRecord(MEASUREMENTS, MEASUREMENTS + "_docs", MEASUREMENTS + "_namespace", false);
                 measurementSchema.setFields(measurementFields);
                return Schema.createArray(measurementSchema);

1 Ответ

0 голосов
/ 11 января 2020

Если вы используете Java, я бы предложил использовать плагин Avro Maven для создания класса Java. Таким образом, вам не нужно выяснять, как создать GenericRecord.

Предполагая, что карта на самом деле вам не нужна, вы можете использовать записи для объектов

{
  "type" : "record",
  "name" : "Item",
  "fields" : [ {
    "name" : "valueMap",
    "type" : {
      "type" : "record",
      "name" : "ValueMap",
      "fields" : [ {
        "name" : "num",
        "type" : "int"
      }, {
        "name" : "pos",
        "type" : {
          "type" : "record",
          "name" : "Point",
          "fields" : [ {
            "name" : "type",
            "type" : "string"
          }, {
            "name" : "coord",
            "type" : {
              "type" : "array",
              "items" : "double"
            }
          } ]
        }
      } ]
    }
  }, {
    "name" : "id",
    "type" : "string"
  }, {
    "name" : "ph",
    "type" : "string"
  } ]
}

, которые я получил от этого IDL

protocol MyProtocol {
  record Point {
    string type ;
    array<double> coord ;
  }
  record ValueMap {
    int num ;
    Point pos ;
  }

  record Item {
     ValueMap valueMap;
    string id;
    string ph;
  }
}
...