मैं स्काला के साथ एव्रो मैप कॉम्प्लेक्स टाइप को क्रमबद्ध/deserialize करने की कोशिश कर रहा हूँ।

अक्रमांकन के बाद, मैं हैश मैप को JSON में बदलने के लिए जैक्सन का उपयोग नहीं कर सकता।

मैं निम्नलिखित आउटपुट की उम्मीद कर रहा था:

{"MyKey2":"MyValue2", "MyKey1":MyValue1"}

लेकिन इसके बजाय मुझे निम्न आउटपुट मिल रहा है:

{"MyKey2":{"बाइट्स":"TXlWYWx1ZTI=","Length":8,"byteLength":8},"MyKey1":{"bytes":"TXlWYWx1ZTE=","length":8,"byteLength ":8}}

अक्रमांकन के बाद हैश मैप को कैसे संभालना है इस पर कोई सुराग? कोड:

import java.io.ByteArrayOutputStream

import com.fasterxml.jackson.databind.ObjectMapper
import org.apache.avro.Schema
import org.apache.avro.generic.GenericData.Record
import org.apache.avro.generic.GenericRecord
import org.apache.avro.io._
import org.apache.avro.specific.{SpecificDatumReader, SpecificDatumWriter}

object ScalaSandbox {

  def main(args: Array[String]) {

    //Avro Schema and Schema Parser
    val userSchema =
      """
        |{
        |  "type":"record",
        |  "name":"myrecord",
        |  "fields": [
        |    {"name": "test_str", "type":"string"},
        |    {"name": "test_map", "type": ["null", {"type": "map", "values": "string"}]}
        |  ]
        |}
      """.stripMargin
    val parser = new Schema.Parser()
    val schema = parser.parse(userSchema)

    //Create Record
    val f2map = new java.util.HashMap[String,String]
    f2map.put("MyKey1", "MyValue1")
    f2map.put("MyKey2", "MyValue2")
    val avroRecord: Record = new Record(schema)
    avroRecord.put("test_str", "test")
    avroRecord.put("test_map", f2map)

    //Serialize Record to Avro
    val writer = new SpecificDatumWriter[GenericRecord](schema)
    val out = new ByteArrayOutputStream()
    val encoder: BinaryEncoder = EncoderFactory.get().binaryEncoder(out, null)
    writer.write(avroRecord, encoder)
    encoder.flush()
    out.close()
    val serializedBytes: Array[Byte] = out.toByteArray()

    //Deserialize Record from Avro
    val reader: DatumReader[GenericRecord] = new SpecificDatumReader[GenericRecord](schema)
    val decoder: Decoder = DecoderFactory.get().binaryDecoder(serializedBytes, null)
    val userData: GenericRecord = reader.read(null, decoder)

    //Convert HashMap to JSON
    val test_str: String = userData.get("test_str").toString
    val test_map: java.util.HashMap[String,String] = userData.get("test_map").asInstanceOf[java.util.HashMap[String,String]]
    val example = new Example(test_str, test_map)

    println("toString of HashMap: " + example.get_map.toString) // {MyKey2=MyValue2, MyKey1=MyValue1}
    println("writeValueAsString of Hashmap: " + example.get_map_json) // {"MyKey2":"MyValue2", "MyKey1":MyValue1"}
  }

  class Example(str_field: String, map_field: java.util.HashMap[String,String]) {
    val mapper = new ObjectMapper()
    def get_str: String = str_field
    def get_map: java.util.HashMap[String,String] = map_field
    def get_map_json: String = mapper.writeValueAsString(map_field)
  }

}
0
Alexandre Juma 2 अगस्त 2019, 21:26

2 जवाब

सबसे बढ़िया उत्तर

डिसेरिएलाइज़्ड मैप्स को पार्स करने के लिए जैक्सन लाइब्रेरी का उपयोग ठीक से काम नहीं कर रहा था क्योंकि एवरो 1.5 के बाद से, एवरो मैप कॉम्प्लेक्स डेटा टाइप org.apache.avro.util.Utf8 का उपयोग करता है।

यदि मैं deserialized Map ऑब्जेक्ट्स को java.util.HashMap[Utf8,Utf8] के उदाहरणों के रूप में उपयोग करता हूं, तो मैं अपने Map KV को बहुत ही अप्रभावी तरीके से Json में बदलने में सक्षम था।

वैसे भी, मैं गलत तरीके से कुछ ऐसा करने की कोशिश कर रहा था जिसे एवरो पुस्तकालय jsonEncoder का उपयोग करके बहुत आसानी से कर सकते हैं।

इसलिए, यह मानते हुए कि हमने कुछ एवरो पेलोड को GenericRecords में डिसेरिएलाइज़ कर दिया है, हम इसे इस तरह से Json में बदल सकते हैं:

  def convertGenericRecordtoJson(record: GenericRecord): String = {
    val outputStream = new ByteArrayOutputStream()
    val jsonEncoder = EncoderFactory.get().jsonEncoder(record.getSchema,outputStream)
    val datumWriter = new GenericDatumWriter[GenericRecord](record.getSchema)
    datumWriter.write(record, jsonEncoder)
    jsonEncoder.flush
    outputStream.flush
    return new String(outputStream.toByteArray, Charset.forName("UTF-8"))
  }

यह फ़ंक्शन मान्य JSON स्ट्रिंग्स का परिणाम देगा:

{"test_str":"test","test_map":{"map":{"MyKey2":"MyValue2",,"MyKey1":"MyValue1"}}}

0
Alexandre Juma 6 अगस्त 2019, 12:31

कृपया उदाहरण वर्ग mapper.writeValueAsString कोड में परिवर्तन करें। हो सकता है कि जैक्सन लाइब्रेरी में कोई समस्या हो।

mapper.writeValueAsString(map_field.toString.replaceAll("=", ":"))
0
Ravi 3 अगस्त 2019, 18:41