Как десериализовать JSON с помощью разметки U ' unicode в Java?


У меня есть это тело ответа HTTP для десериализации:

String response = "result : {'url': u'https://somedomain/', 'fields': {'policy': 
u'eyJjb25kaXRpb25zIjogW1siYfgfhudGVudC1sZjMyWiJ9', 'AWSAccessKeyId': 
u'ASIccccccNA', 'x-amz-security-token': 'FQofgF', 'key': u'bbb.file', 
'signature': u'rm9gdflkjfs='}}"

Я использую Джексона.core (2.9.0) java package и lib (также пробовали GSON) и получаем такую ошибку:

Exception in thread "main" com.fasterxml.jackson.core.JsonParseException: 
Unrecognized token 'u': was expecting ('true', 'false' or 'null')

Код десериализации:

MyResponse deserializedResponse = new ObjectMapper()
  .configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true)
  .configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true)
  .configure(JsonGenerator.Feature.ESCAPE_NON_ASCII, true)
                        .readValue(response, MyResponse.class);

Я рассматривал что-то вроде этого, но мне кажется, что должен быть лучший / безопасный способ:

String sanitizedResponse = response.replaceAll("u'", "'"); 

--

Использование Java 1.8.

Любая помощь ценится.

2 2

2 ответа:

Поскольку python вызвал эту проблему, я думаю, что лучшее решение-позволить python исправить ее ; -). К счастью, с jython вы можете придерживаться чистой реализации java.

Сначала вам нужно добавить автономную зависимость jython в ваш pom.xml:

<dependencies>
    <dependency>
        <groupId>org.python</groupId>
        <artifactId>jython-standalone</artifactId>
        <version>2.7.1</version>
    </dependency>
    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>2.5</version>
    </dependency>
</dependencies>

(Как вы можете видеть, я также использовал apache commons io для своего примера, поэтому я также добавил его)

Я поместил вашу (недопустимую) строку json в текстовый файл "c:/temp/json.txt " , который имеет следующее содержание:

{'url': u'https://somedomain/', 'fields': {'policy': 
u'eyJjb25kaXRpb25zIjogW1siYfgfhudGVudC1sZjMyWiJ9', 'AWSAccessKeyId': 
u'ASIccccccNA', 'x-amz-security-token': 'FQofgF', 'key': u'bbb.file', 
'signature': u'rm9gdflkjfs='}}

Теперь вот код для чтения файла json, настройки интерпретатора Python и передачи json для его очистки:

String content = FileUtils.readFileToString(new File("c:/temp/json.txt"), "UTF-8");

PythonInterpreter pi = new PythonInterpreter();
pi.exec("import json");
pi.exec("jsondata = " + content);
pi.exec("jsonCleaned = json.dumps(jsondata)");
PyObject jsonCleaned = (PyObject) pi.get("jsonCleaned");
System.out.println(jsonCleaned.asString());
pi.close();

Вывод:

{"url": "https://somedomain/", "fields": {"signature": "rm9gdflkjfs=", "AWSAccessKeyId": "ASIccccccNA", "x-amz-security-token": "FQofgF", "key": "bbb.file", "policy": "eyJjb25kaXRpb25zIjogW1siYfgfhudGVudC1sZjMyWiJ9"}}

Когда вы помещаете это в валидатор json (https://jsonlint.com/) теперь вы можете видеть, что это действительный json. Я не могу сказать, достаточно ли хороша производительность для вашего случая использования, поэтому вы должны проверить это.

Замечание: В Eclipse там, кажется, ошибка с языка Jython версия. Он показывает следующую ошибку:

console: Failed to install '': java.nio.charset.UnsupportedCharsetException: cp0.

Хотя он работает, тем не менее, вы можете избавиться от него, добавив следующий VM-аргумент в свою конфигурацию запуска:

-Dpython.console.encoding=UTF-8

Remark2: для полноты и полного ответа на этот вопрос-вот как можно десериализовать очищенный JSON:

Добавьте зависимость GSON в ваш pom.xml:

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.8.2</version>
</dependency>

Создать классы представления:

Класс информации

public class Info {
    private String url;
    private Fields fields;

    public String getUrl() {
        return url;
    }

    public void setUrl(String url) {
        this.url = url;
    }

    public Fields getFields() {
        return fields;
    }

    public void setFields(Fields fields) {
        this.fields = fields;
    }

}

Поля класс

import com.google.gson.annotations.SerializedName;

public class Fields {
    private String signature;
    private String AWSAccessKeyId;

    @SerializedName("x-amz-security-token")
    private String x_amz_security_token;

    private String key;
    private String policy;

    public String getSignature() {
        return signature;
    }

    public void setSignature(String signature) {
        this.signature = signature;
    }

    public String getAWSAccessKeyId() {
        return AWSAccessKeyId;
    }

    public void setAWSAccessKeyId(String aWSAccessKeyId) {
        AWSAccessKeyId = aWSAccessKeyId;
    }

    public String getX_amz_security_token() {
        return x_amz_security_token;
    }

    public void setX_amz_security_token(String x_amz_security_token) {
        this.x_amz_security_token = x_amz_security_token;
    }

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }

    public String getPolicy() {
        return policy;
    }

    public void setPolicy(String policy) {
        this.policy = policy;
    }

}

Наконец, добавьте следующий код после того, как вы получите очищенный JSON:

Gson gson = new Gson();
Info info = gson.fromJson(jsonCleaned.asString(), Info.class);

Вам нужно использовать следующее регулярное выражение, которое заменяет u' из начала границы слов для замены на '

String regexPattern = "(\\bu')";