【问题标题】:How to transform JSON message to valid JSON for avro schema with nullable fields?如何将 JSON 消息转换为具有可为空字段的 avro 模式的有效 JSON?
【发布时间】:2019-05-14 15:41:40
【问题描述】:

我想使用 avro-schema 向 kafka 主题发送 JSON 消息。

avro-schema 允许多种类型:

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

如果值为 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 元素。我该如何解决这个问题?

【问题讨论】:

  • 我知道这并不能回答你的问题,但我喜欢那句老话“有些人在遇到问题时会想‘我知道,我会使用正则表达式。’”现在他们有两个问题。”我将敦促您考虑使用Jackson 并使用jsonschema2pojo 创建您的json 类。 Baeldung has lots of great tutorials on Jackson 如果您需要帮助。
  • @hooknc,我有一个从 avro 模式生成的 java 类。我从我的模型中使用 Gson 生成 JSON。属性上的注解可以覆盖生成过程吗?

标签: java json regex avro


【解决方案1】:

我可以将typeA 转换为:

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

但是typeBtypeC 对我来说太难了,因为我无法精确匹配。不知何故,当我尝试用数组替换 typeB 时。另一个地方也被替换了,这是我们不想要的。

如果您或其他人可以解决该问题,那么typeC 也可以轻松解决。因为typeBtypeC 是相似的。我也很好奇解决方案是什么。所以让我知道!

我现在将分享我如何修复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
},

【讨论】:

    【解决方案2】:

    这不是很有趣,因为所有值的名称,但Jackson 工作得很好。

    我把你想要的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 生成的类来测试 Jackson。

    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 ]
          } ]
        } ]
      }
    }
    

    哪个,我认为与您的要求相当接近。

    【讨论】:

      猜你喜欢
      • 2020-01-17
      • 1970-01-01
      • 1970-01-01
      • 2021-12-01
      • 1970-01-01
      • 2016-12-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多