Groovy / Grails Пролиферация escape-символа "\" в строке - PullRequest
0 голосов
/ 28 сентября 2018

Это довольно странная проблема.Я тестирую интеграцию сервиса Grails и соответствующего класса домена.Одним из свойств этого класса домена является String, который содержит JSON.Поле базы данных тоже json, и есть пользовательский тип значения Hibernate, который выполняет необходимое преобразование.Уже много лет он работает в другом доменном классе.

class MyDomain {
    String data
    static mapping = {
        data type: StringJsonUserType
    }
}

Пока все хорошо.В моем тесте я имитирую входной объект для моего метода обслуживания, который в конечном итоге будет содержать и возвращать нужную строку JSON.

private MockedClass mockClass() {
    // JsonRepresentable declares asJson() method.
    def data = GroovyMock(JsonRepresentable)
    data.asJson() >> "{\"content\":\"irrelevant\"}"

    def mockClass = GroovyMock(MockedClass)
    mockClass.getData() >> data

    return mockClass
}

Метод обслуживания (упрощенный):

void persist(MockedClass mock) {
    String string = mock.data.asJson()
    def domain = new MyDomain(data: mock.data.asJson())
    domain.save()
}

Когда явойдя в этот код с помощью отладчика, я сразу вижу, что строка изменилась с {"content":"irrelevant"} в переменной string на "{\"content\":\"irrelevant\"}" в переменной domain.

Теперь логично, что вмой тест сравнения сохраненной строки класса домена не совпадает с ложным вводом.

Так выглядит MyDomain.data данные при чтении из базы данных:

"\"\\\"{\\\\\\\"content\\\\\\\":\\\\\\\"irrelevant\\\\\\\"}\\\"\""

Это та же самая строка, проанализированная с new JsonSlurper().parseText(MyDomain.data):

"\"{\\\"content\\\":\\\"irrelevant\\\"}\""

Вот смоделированная строка, проанализированная с помощью JsonSlurper (как указано выше):

[content:irrelevant]

Очевидно, последний пример - это то, что я ожидаю.Кто-нибудь может сказать мне, почему Groovy / Grails добавляет большую часть дерьма \\ к моей простой и правильно экранированной строке?Я мог бы даже попробовать Groovy-строку '{"content":"irrelevant"}', но это не имеет никакого значения.

1 Ответ

0 голосов
/ 02 октября 2018

Просто случайно (в поисках некоторых других странных проблем, которые возникли после переименования пакета), я выяснил, в чем причина проблемы.В моем доменном классе у меня есть не только свойство String, но и временный метод получения и установки, который возвращает объект JSON из этой строки или принимает объект JSON и превращает его в строку.

class MyDomain {
    String data
    static mapping = {
        data type: StringJsonUserType
    }

    static transients = ['dataJson']

    def getDataJson() {
        return new JsonSlurper().parseText(data)
    }

    void setDataJson(def data) {
        data = JsonOutput.toJson(data)
    }
}

К сожалению, ябыла опечатка в setDataJson.Его имя было setData, и поэтому оно использовалось в качестве установщика для моего String в методе обслуживания.

void persist(MockedClass mock) {
    String string = mock.data.asJson()
    def domain = new MyDomain(data: mock.data.asJson())
    domain.save()
}

Это означает, что JsonOutput.toJson(data) преобразовал мою строку JSON в другую строку JSON, и именно здесьвсе дополнительные escape-символы взяты из.

Мораль истории: переключитесь на правильно скомпилированный язык, который применяет систему типов во время компиляции.

...