Сериализация массивов, содержащих объект для Avro в Swift - PullRequest
1 голос
/ 10 января 2020

В настоящее время я пытаюсь сгенерировать AvroValue, составленную из AvroRecord, которая состоит из различных AvroValues, AvroRecords, AvroArrays и AvroArrays, содержащих AvroRecords.

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

Я мог бы разработать решение для большинства из них, однако создание AvroArrays, содержащего AvroRecords, не работает должным образом.

- При кодировании объекта из 6 переменных я получаю следующий байтовый массив. [2, 2, 6, 117, 114, 108, 2, 2, 2, 2, 2],

- я получаю следующий для того же объекта, но в этом случае в AvroArray. [2, 2] Что не имеет смысла.

Это сложная вещь, которую я объясню, поэтому я собираюсь посеять оба кода.

Наконец, просто отметим, что я почти уверен, что неверный код находится в методе "avroNullableArrayValue" или в способе, которым он вызывается и используется.

AvroRecord Пример: (Работает)

let jsonSchemaResult = "  {\r\n  \"namespace\": \"x\",\r\n  \"doc\": \"1\",\r\n  \"type\": \"record\",\r\n  \"name\": \"event\",\r\n  \"fields\": [\r\n    {\"name\": \"event_httppageload\",  \"type\": [\"null\", {\r\n       \"type\": \"record\",\r\n       \"name\": \"EventHttppageloadRecord\",\r\n       \"fields\": [\r\n          {\"name\": \"url\", \"type\": [\"null\", \"string\"]},\r\n          {\"name\": \"setup_time\", \"type\": [\"null\", \"int\"]},\r\n          {\"name\": \"duration\", \"type\": [\"null\", \"int\"]},\r\n          {\"name\": \"data_downloaded\", \"type\": [\"null\", \"int\"]},\r\n          {\"name\": \"is_error\", \"type\": [\"null\", \"boolean\"]},\r\n          {\"name\": \"error_code\", \"type\": [\"null\", {\"type\": \"enum\", \"name\": \"HttpErrorCodeEnum\", \"symbols\" : [\"NO_ERROR\", \"FILE_NOT_FOUND\", \"NETWORK_ERROR\", \"NETWORK_TIMEOUT\",\"INTERNAL_ERROR\"]}]}\r\n       ]\r\n       \r\n    }]}]}"

 let schema = Schema(jsonSchemaResult)
 let avroValue: AvroValue
//Please ignore the variable "result", it is never used
 avroValue = result.toAvro()
 let encodedBytes = avroValue.encode(schema!)

extension ResultObject : AvroValueConvertible {
    public func toAvro() -> AvroValue {
        let object1: DCUrlResult = DCUrlResult.init(url: "url", label: "label", loadTime: 111, pingTime: 222, pageSize: 333, error: true)

        let returnThink = AvroValue.avroRecordValue([
            "event_httppageload" : avroNullableRecordValue(v: object1, converter: {
                let newAvro = AvroValue.avroRecordValue([
                    "url" : $0.url.toAvroString(),
                    "setup_time" : $0.url.toAvroString(),
                    "duration" : $0.url.toAvroString(),
                    "data_downloaded" : $0.url.toAvroString(),
                    "is_error" : $0.url.toAvroString(),
                    "error_code" : $0.url.toAvroString()
                ])
                return newAvro
            })
        ])
    }
}

 public func avroNullableRecordValue<T>(v: T?, converter: (T) -> AvroValue) -> AvroValue{
     if(v == nil) {
         let box = Box(AvroValue.avroNullValue)
         return .avroUnionValue(0, box)
     } else {
         let pend2 = converter(v!)
         let box = Box(pend2)
         return .avroUnionValue(1, box)
     }
 }

extension Optional where Wrapped == String {
    public func toAvroString() -> AvroValue {
        switch self {
        case .none:
            let box = Box(AvroValue.avroNullValue)
            return .avroUnionValue(0, box)
        case .some(let v):
            let box = Box(v.toAvro())
            return .avroUnionValue(1, box)
        }
    }
}
extension Optional where Wrapped == Int32 {
    public func toAvro() -> AvroValue {
        switch self {
        case .none:
            let box = Box(AvroValue.avroNullValue)
            return .avroUnionValue(0, box)
        case .some(let v):
            let box = Box(v.toAvro())
            return .avroUnionValue(1, box)
        }
    }
}
extension Optional where Wrapped == Bool {
    public func toAvro() -> AvroValue {
        switch self {
        case .none:
            let box = Box(AvroValue.avroNullValue)
            return .avroUnionValue(0, box)
        case .some(let v):
            let box = Box(v.toAvro())
            return .avroUnionValue(1, box)
        }
    }
}

AvroArray Пример: (Не работает)

let jsonSchemaResult = "{\r\n  \"namespace\": \"x\",\r\n  \"doc\": \"1\",\r\n  \"type\": \"record\",\r\n  \"name\": \"event\",\r\n  \"fields\": [\r\n    {\"name\": \"event_httppageload\",  \"type\": [\"null\", {\r\n    \"type\": \"array\",\r\n      \"items\": {\r\n         \"type\": \"record\",\r\n         \"name\": \"EventHttppageloadRecord\",\r\n         \"fields\": [\r\n            {\"name\": \"url\", \"type\": [\"null\", \"string\"]},\r\n            {\"name\": \"setup_time\", \"type\": [\"null\", \"int\"]},\r\n            {\"name\": \"duration\", \"type\": [\"null\", \"int\"]},\r\n            {\"name\": \"data_downloaded\", \"type\": [\"null\", \"int\"]},\r\n            {\"name\": \"is_error\", \"type\": [\"null\", \"boolean\"]},\r\n            {\"name\": \"error_code\", \"type\": [\"null\", {\"type\": \"enum\", \"name\": \"HttpErrorCodeEnum\", \"symbols\" : [\"NO_ERROR\", \"FILE_NOT_FOUND\", \"NETWORK_ERROR\", \"NETWORK_TIMEOUT\",\"INTERNAL_ERROR\"]}]}\r\n         ]\r\n      }\r\n    }]}]}"

let schema = Schema(jsonSchemaResult)
let avroValue: AvroValue
//Please ignore the variable "result", it is never used
avroValue = result.toAvro()
let encodedBytes = avroValue.encode(schema!)

extension ResultObject : AvroValueConvertible {
    public func toAvro() -> AvroValue {

       let object1: DCUrlResult = DCUrlResult.init(url: "url", label: "label", loadTime: 111, 
       pingTime: 222, pageSize: 333, error: true)
       var randomarray: Array<DCUrlResult> = Array<DCUrlResult>.init()
       randomarray.append(object1)

       let returnThinkk = AvroValue.avroRecordValue([
                "event_httppageload" : avroNullableArrayValue(v: randomarray, converter:{
                    $0?.map({avroNullableRecordValue(v: $0, converter: {
                           let newAvro = AvroValue.avroRecordValue([
                          "url" : $0.url.toAvroString(),
                          "setup_time" : $0.url.toAvroString(),
                          "duration" : $0.url.toAvroString(),
                          "data_downloaded" : $0.url.toAvroString(),
                          "is_error" : $0.url.toAvroString(),
                          "error_code" : $0.url.toAvroString()
                            ])
                            return newAvro
                        })})
                    })
                ])
            }
        }

public func avroNullableArrayValue<T>(v: [T]?, converter: ([T]?) -> [AvroValue]?) -> AvroValue {
         if(v == nil) {
             //return avroNilValue()
             let box = Box(AvroValue.avroNullValue)
             return .avroUnionValue(0, box)
         } else {
             let pend2 = converter(v!)!
             let box = Box(AvroValue.avroArrayValue(pend2))
             return .avroUnionValue(1, box)
         }
     }

extension Optional where Wrapped == String {
     public func toAvroString() -> AvroValue {
         switch self {
         case .none:
             let box = Box(AvroValue.avroNullValue)
             return .avroUnionValue(0, box)
         case .some(let v):
             let box = Box(v.toAvro())
             return .avroUnionValue(1, box)
         }
     }
 }
extension Optional where Wrapped == Int32 {
    public func toAvro() -> AvroValue {
        switch self {
        case .none:
            let box = Box(AvroValue.avroNullValue)
            return .avroUnionValue(0, box)
        case .some(let v):
            let box = Box(v.toAvro())
            return .avroUnionValue(1, box)
        }
    }
}
extension Optional where Wrapped == Bool {
    public func toAvro() -> AvroValue {
        switch self {
        case .none:
            let box = Box(AvroValue.avroNullValue)
            return .avroUnionValue(0, box)
        case .some(let v):
            let box = Box(v.toAvro())
            return .avroUnionValue(1, box)
        }
    }
}

Это схема для AvroRecord :

{
  "namespace": "x",
  "doc": "1",
  "type": "record",
  "name": "event",
  "fields": [
    {"name": "event_httppageload",  "type": ["null", {
       "type": "record",
       "name": "EventHttppageloadRecord",
       "fields": [
          {"name": "url", "type": ["null", "string"]},
          {"name": "setup_time", "type": ["null", "int"]},
          {"name": "duration", "type": ["null", "int"]},
          {"name": "data_downloaded", "type": ["null", "int"]},
          {"name": "is_error", "type": ["null", "boolean"]},
          {"name": "error_code", "type": ["null", "string"]}
       ]

    }]}]}

Это схема для AvroArray, содержащая AvroRecords:

{
  "namespace": "x",
  "doc": "1",
  "type": "record",
  "name": "event",
  "fields": [
    {"name": "event_httppageload",  "type": ["null", {
    "type": "array",
      "items": {
         "type": "record",
         "name": "EventHttppageloadRecord",
         "fields": [
            {"name": "url", "type": ["null", "string"]},
            {"name": "setup_time", "type": ["null", "int"]},
            {"name": "duration", "type": ["null", "int"]},
            {"name": "data_downloaded", "type": ["null", "int"]},
            {"name": "is_error", "type": ["null", "boolean"]},
            {"name": "error_code", "type": ["null", "string"]}
         ]
      }
    }]}]}

Я использую для этого библиотеку BlueSteel для Swift , которая теоретически основано на Apache Avro .

Пожалуйста, не стесняйтесь спрашивать больше кода в случае, если он вам нужен, чтобы выяснить, что может быть не так.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...