В настоящее время я пытаюсь сгенерировать 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 .
Пожалуйста, не стесняйтесь спрашивать больше кода в случае, если он вам нужен, чтобы выяснить, что может быть не так.