Как преобразовать JSON-сообщение в действительный JSON для схемы avro с пустыми полями? - PullRequest
0 голосов
/ 14 мая 2019

Я хотел бы отправить сообщение JSON в тему kafka с авро-схемой.

Авро-схема допускает несколько типов:

{  
   "name":"typeA",
   "type":[  
      "int",
      "null"
   ],
   "default":null
}

Если значение равно нулю, все в порядке.Если тип int, как в этом случае, это должно быть указано явно.Посмотреть этот билет AVRO-1582 .

У меня есть этот JSON:

{
   "typeA":12345,
   "typeB":[
      {
         "feature":1,
         "value":"1"
      },
      {
         "feature":2,
         "value":"2"
      }
   ],
   "typeC":[
      {
         "a":12345,
         "data":[
            {
               "a":12345,
               "b":[
                  12345,
                  12345,
                  12345
               ]
            }
         ]
      }
   ]
}

Я хотел бы преобразовать в этот JSON:

{
   "typeA":{
      "int":12345
   },
   "typeB":{
      "array":[
         {
            "feature":1,
            "value":"1"
         },
         {
            "feature":2,
            "value":"2"
         }
      ]
   },
   "typeC":{
      "array":[
         {
            "a":12345,
            "data":[
               {
                  "a":12345,
                  "b":[
                     12345,
                     12345,
                     12345
                  ]
               }
            ]
         }
      ]
   }
}

Можно ли преобразовать "typeA":12345 в "typeA":{"int":12345}?Существует простой способ решения этой проблемы?

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

json.replaceAll("typeA\":([^,]*),\"", "typeA\":{\"int\":$1},\"");

Трудно обрабатывать массивы или последний элемент JSON,Как я могу решить эту проблему?

Ответы [ 2 ]

0 голосов
/ 15 мая 2019

Это было не очень весело, из-за имен всех значений, но Джексон работал просто отлично.

Я вставил json, который вы хотели в json2pojo :

{
  "typeA":{
     "int":12345
  },
  "typeB":{
     "array":[
        {
           "feature":1,
           "value":"1"
        },
        {
           "feature":2,
           "value":"2"
        }
     ]
  },
  "typeC":{
     "array":[
        {
           "a":12345,
           "data":[
              {
                 "a":12345,
                 "b":[
                    12345,
                    12345,
                    12345
                 ]
              }
           ]
        }
     ]
  }
}

Использовал функцию загрузки в виде zip-файла для переноса классов в мою локальную среду разработки.

Затем создал это чудовище класса, который проверяет Джексона с помощью сгенерированных классов из json2pojo.

public class JacksonSerialization {

   public static void main(String... args) throws Exception {

       TypeA typeA = new TypeA();
       typeA.setInt(12345);

       TypeB typeB = new TypeB();
       ArrayList<Array> arrays = new ArrayList<>();
       arrays.add(createArray(1, "1"));
       arrays.add(createArray(2, "2"));
       typeB.setArray(arrays);

       TypeC typeC = new TypeC();

       ArrayList<Integer> integers = new ArrayList<>();
       integers.add(12345);
       integers.add(12345);
       integers.add(12345);

       ArrayList<Datum> data = new ArrayList<>();
       Datum datum = new Datum();
       datum.setA(12345);
       datum.setB(integers);
       data.add(datum);

       Array_ array_ = new Array_();
       array_.setA(12345);
       array_.setData(data);

       ArrayList<Array_> array_s = new ArrayList<>();
       array_s.add(array_);
       typeC.setArray(array_s);

       Example example = new Example();
       example.setTypeA(typeA);
       example.setTypeB(typeB);
       example.setTypeC(typeC);

       ObjectMapper mapper = new ObjectMapper();
       mapper.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, false);
       mapper.configure(SerializationFeature.INDENT_OUTPUT, true);

       ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
       //mapper.writeValue(byteArrayOutputStream, example);
       mapper.writeValue(new File("target/Example.json"), example);

       String json = byteArrayOutputStream.toString();

       json = StringEscapeUtils.escapeCsv(json);

       System.out.println(json);
   }

   private static Array createArray(Integer feature, String value) {

       Array array = new Array();
       array.setFeature(feature);
       array.setValue(value);

       return array;
   }
}

Который при запуске этого класса создает следующий json.

{
  "typeA" : {
    "int" : 123456
  },
  "typeB" : {
    "array" : [ {
      "feature" : 1,
      "value" : "1"
    }, {
      "feature" : 2,
      "value" : "2"
    } ]
  },
  "typeC" : {
    "array" : [ {
      "a" : 12345,
      "data" : [ {
        "a" : 12345,
        "b" : [ 12345, 12345, 12345 ]
      } ]
    } ]
  }
}

Что, я думаю, довольно близко к тому, что вы просили.

0 голосов
/ 15 мая 2019

Я могу преобразовать typeA в:

"typeA":{
    "int":12345
},

Но typeB и typeC были для меня слишком сложными, потому что я не мог точно их сопоставить.Как-то, когда я пытаюсь заменить typeB на массив.Также заменяется другое место, которое нам не нужно.

Если вы или кто-то еще можете решить эту проблему, то typeC также можно легко исправить.Потому что typeB и typeC похожи.Мне также любопытно, что решение.Итак, дайте мне знать!

Теперь я поделюсь, как я исправил typeA.Вот код Java:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Test {

    public static void main(String[] args) {
        String line = "{\r\n" +
                "   \"typeA\":12345,\r\n" +
                "   \"typeB\":[\r\n" +
                "      {\r\n" +
                "         \"feature\":1,\r\n" +
                "         \"value\":\"1\"\r\n" +
                "      },\r\n" +
                "      {\r\n" +
                "         \"feature\":2,\r\n" +
                "         \"value\":\"2\"\r\n" +
                "      }\r\n" +
                "   ],\r\n" +
                "   \"typeC\":[\r\n" +
                "      {\r\n" +
                "         \"a\":12345,\r\n" +
                "         \"data\":[\r\n" +
                "            {\r\n" +
                "               \"a\":12345,\r\n" +
                "               \"b\":[\r\n" +
                "                  12345,\r\n" +
                "                  12345,\r\n" +
                "                  12345\r\n" +
                "               ]\r\n" +
                "            }\r\n" +
                "         ]\r\n" +
                "      }\r\n" +
                "   ]\r\n" +
                "}";

        String regex = "(\\\"type[A-Z]\\\"):(\\d*)|(\\[.*)|(.*\\])";
        Pattern pattern = Pattern.compile(regex);
        Matcher matcher = pattern.matcher(line);
        while (matcher.find()) {
             if(matcher.group().equals("\"typeA\":12345")) {
                 String regex2 = "(\\\"typeA\\\"):(\\d*)";
                 line = line.replaceAll(regex2, "$1:{\"int\":$2}");
             }

             if(matcher.group().equals("\"typeB\":") ) {
                 //I couldn't finish this typeB, because it's too difficult
//                 String regex3 = "(\\\"type[B]\\\"):|(\\s{3}],)";
//                 line = line.replaceAll(regex3, "$1 :{ array: $2 ");
             }
        }
         System.out.println("line: " + line);
    }
}

Сначала я использовал это регулярное выражение (\"type[A-Z]\"):(\d*)|(\[.*)|(.*\]).Это регулярное выражение дает нам несколько групп, на которые мы хотим посмотреть.

В конце концов цикл while запускается "typeA":12345 И здесь мы используем регулярное выражение ("typeA"):(\d*).Мы используем это регулярное выражение для преобразования typeA в:

"typeA":{
    "int":12345
},
...