Преобразование строки HOCON в объект Java

Один из моих веб-сервисов возвращается ниже строки Java:

[
  {
    id=5d93532e77490b00013d8862, 
    app=null,
    manufacturer=pearsonEducation, 
    bookUid=bookIsbn, 
    model=2019,
    firmware=[1.0], 
    bookName=devotional, 
    accountLinking=mandatory
  }
]

У меня есть эквивалентный объект Java для указанной выше строки. Я хотел бы привести или преобразовать приведенную выше строку Java в объект Java.

Я не мог ввести его, так как это строка, а не объект. Итак, я пытался преобразовать строку Java в строку JSON, после чего я мог записать эту строку в объект Java, но мне не удалось получить исключение invalid character "=".

Можете ли вы изменить веб-службу, чтобы она возвращала JSON?

Это невозможно. Они не меняют свои контракты. Было бы очень просто, если бы они вернули JSON.


person VelNaga    schedule 08.10.2019    source источник
comment
Они не ясны с форматом, поэтому мы можем ожидать запятую в строке. У нас есть другой путь?   -  person VelNaga    schedule 08.10.2019
comment
@ f1sh На самом деле это стандартный формат. Он называется HOCON.   -  person ETO    schedule 08.10.2019


Ответы (3)


Формат, который возвращает ваш веб-сервис, имеет собственное имя HOCON. (Подробнее об этом можно прочитать здесь)

Вам не нужен собственный парсер. Не пытайтесь изобретать велосипед. Вместо этого используйте существующий.


Добавьте эту зависимость maven в свой проект:

<dependency>
    <groupId>com.typesafe</groupId>
    <artifactId>config</artifactId>
    <version>1.3.0</version>
</dependency>

Затем проанализируйте ответ следующим образом:

Config config = ConfigFactory.parseString(text);

String id = config.getString("id");
Long model = config.getLong("model");

Существует также возможность разобрать всю строку в POJO:

MyResponsePojo response = ConfigBeanFactory.create(config, MyResponsePojo.class);

К сожалению, этот парсер не поддерживает значения null. Поэтому вам нужно будет обрабатывать исключения типа com.typesafe.config.ConfigException.Null.


Другой вариант — преобразовать строку HOCON в JSON:

String hoconString = "...";
String jsonString = ConfigFactory.parseString(hoconString)
                                 .root()
                                 .render(ConfigRenderOptions.concise());

Затем вы можете использовать любой преобразователь JSON-to-POJO.

person ETO    schedule 08.10.2019

Что ж, это определенно не лучший ответ, который можно здесь дать, но, по крайней мере, это возможно…

Манипулируйте String небольшими шагами, чтобы получить Map<String, String>, который можно обработать. Посмотрите этот пример, он очень простой:

public static void main(String[] args) {
    String data = "[\r\n" 
            + "  {\r\n"
            + "    id=5d93532e77490b00013d8862, \r\n"
            + "    app=null,\r\n"
            + "    manufacturer=pearsonEducation, \r\n"
            + "    bookUid=bookIsbn, \r\n"
            + "    model=2019,\r\n"
            + "    firmware=[1.0], \r\n"
            + "    bookName=devotional, \r\n"
            + "    accountLinking=mandatory\r\n"
            + "  }\r\n"
            + "]";

    // manipulate the String in order to have
    String[] splitData = data
            // no leading and trailing [ ] - cut the first and last char
            .substring(1, data.length() - 1)
            // no linebreaks
            .replace("\n", "")
            // no windows linebreaks
            .replace("\r", "")
            // no opening curly brackets
            .replace("{", "")
            // and no closing curly brackets.
            .replace("}", "")
            // Then split it by comma
            .split(",");

    // create a map to store the keys and values
    Map<String, String> dataMap = new HashMap<>();

    // iterate the key-value pairs connected with '='
    for (String s : splitData) {
        // split them by the equality symbol
        String[] keyVal = s.trim().split("=");
        // then take the key
        String key = keyVal[0];
        // and the value
        String val = keyVal[1];
        // and store them in the map ——> could be done directly, of course
        dataMap.put(key, val);
    }

    // print the map content
    dataMap.forEach((key, value) -> System.out.println(key + " ——> " + value));
}

Обратите внимание, что я только что скопировал ваш пример String, который мог вызвать разрывы строк, и я думаю, что неразумно просто replace() все квадратные скобки, потому что значение firmware, похоже, включает их в качестве содержимого.

person deHaar    schedule 08.10.2019

На мой взгляд, мы разделили процесс синтаксического анализа на два этапа.

  1. Отформатируйте выходные данные в формате JSON.
  2. Разбирать текст утилитами JSON.

В этом демонстрационном коде я выбираю регулярное выражение в качестве метода форматирования и fastjson в качестве инструмента JSON. Вы можете выбрать Джексона или Гсона. Кроме того, я удаляю [ ], вы можете вернуть его обратно, а затем разобрать в массив.

import com.alibaba.fastjson.JSON;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class SerializedObject {
    private String id;
    private String app;

    static Pattern compile = Pattern.compile("([a-zA-Z0-9.]+)");
    public static void main(String[] args) {
        String str =
                "  {\n" +
                "    id=5d93532e77490b00013d8862, \n" +
                "    app=null,\n" +
                "    manufacturer=pearsonEducation, \n" +
                "    bookUid=bookIsbn, \n" +
                "    model=2019,\n" +
                "    firmware=[1.0], \n" +
                "    bookName=devotional, \n" +
                "    accountLinking=mandatory\n" +
                "  }\n";
        String s1 = str.replaceAll("=", ":");
        StringBuffer sb = new StringBuffer();
        Matcher matcher = compile.matcher(s1);
        while (matcher.find()) {
            matcher.appendReplacement(sb, "\"" + matcher.group(1) + "\"");
        }
        matcher.appendTail(sb);
        System.out.println(sb.toString());

        SerializedObject serializedObject = JSON.parseObject(sb.toString(), SerializedObject.class);
        System.out.println(serializedObject);
    }
}
person caisil    schedule 08.10.2019