FOR JSON PATH возвращает экранированные строки для вложенных объектов - PullRequest
0 голосов
/ 01 апреля 2019

Я пытаюсь написать запрос к UNION объектам из двух связанных таблиц и вернуть результаты Azure SQL Server в виде объектов JSON.У меня возникла проблема с запросом, которую я не могу решить.

Когда я запрашиваю таблицу entity со списком подобъектов grades, используя опцию FOR JSON PATH для возврата объектов в формате JSON, я получаю ожидаемый результат.

Запрос

SELECT 
    entity.name AS name,
    (
    SELECT
        grade_translation.name,
        grade_translation.short_name
    FROM
        entity_grades,
        grade,
        grade_translation,
        language

    WHERE
         entity.id = entity_grades.entity_id
         AND entity_grades.grade_id = grade.id
         AND grade.id = grade_translation.non_translated_id
         AND grade_translation.language_id = language.id
         AND language.short_name = 'en'

    ORDER BY
        entity_grades.[order]

    FOR JSON PATH
    ) AS grades
FROM entity
LEFT JOIN entity_translation ON entity_translation.non_translated_id = entity.id
LEFT JOIN language ON language.id = entity_translation.language_id
WHERE language.short_name = 'en'
FOR JSON PATH

Результат

[{
    "name": "Test Entity 1",
    "about": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Porta lorem mollis aliquam ut porttitor leo. Lacus sed viverra tellus in hac habitasse.Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Integer malesuada nunc vel risus commodo. Neque aliquam vestibulum morbi blandit cursus risus.",
    "grades": [{
        "name": "Grade 9",
        "short_name": "9"
    }, {
        "name": "Grade 10",
        "short_name": "10"
    }, {
        "name": "Grade 11",
        "short_name": "11"
    }, {
        "name": "Grade 12",
        "short_name": "12"
    }]
}, {
    "name": "Test Entity 2",
    "about": "Blah blah blah"
}]

То же самое касается объектовкоторые не имеют переводов.

Запрос (сущности без переводов)

SELECT 
    entity.name AS name,
    (
    SELECT
        grade_translation.name,
        grade_translation.short_name
    FROM
        entity_grades,
        grade,
        grade_translation,
        language

    WHERE
         entity.id = entity_grades.entity_id
         AND entity_grades.grade_id = grade.id
         AND grade.id = grade_translation.non_translated_id
         AND grade_translation.language_id = language.id
         AND language.short_name = 'en'

    ORDER BY
        entity_grades.[order]

    FOR JSON PATH
    ) AS grades
FROM entity
LEFT JOIN entity_translation ON entity_translation.non_translated_id = entity.id
LEFT JOIN language ON language.id = entity_translation.language_id
WHERE entity.id NOT IN (SELECT DISTINCT entity_translation.non_translated_id FROM entity_translation)
FOR JSON PATH

Результат

[{
    "name": "Test Entity 3"
}]

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

Запрос (UNION)

SELECT 
    entity.name AS name,
    (
    SELECT
        grade_translation.name,
        grade_translation.short_name
    FROM
        entity_grades,
        grade,
        grade_translation,
        language

    WHERE
         entity.id = entity_grades.entity_id
         AND entity_grades.grade_id = grade.id
         AND grade.id = grade_translation.non_translated_id
         AND grade_translation.language_id = language.id
         AND language.short_name = 'en'

    ORDER BY
        entity_grades.[order]

    FOR JSON PATH
    ) AS grades
FROM entity
LEFT JOIN entity_translation ON entity_translation.non_translated_id = entity.id
LEFT JOIN language ON language.id = entity_translation.language_id
WHERE language.short_name = 'en'

UNION

SELECT 
    entity.name AS name,
    (
    SELECT
        grade_translation.name,
        grade_translation.short_name
    FROM
        entity_grades,
        grade,
        grade_translation,
        language

    WHERE
         entity.id = entity_grades.entity_id
         AND entity_grades.grade_id = grade.id
         AND grade.id = grade_translation.non_translated_id
         AND grade_translation.language_id = language.id
         AND language.short_name = 'en'

    ORDER BY
        entity_grades.[order]

    FOR JSON PATH
    ) AS grades
FROM entity
LEFT JOIN entity_translation ON entity_translation.non_translated_id = entity.id
LEFT JOIN language ON language.id = entity_translation.language_id
WHERE entity.id NOT IN (SELECT DISTINCT entity_translation.non_translated_id FROM entity_translation)
FOR JSON PATH

Результат

[{
    "name": "Test Entity 1",
    "about": "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Porta lorem mollis aliquam ut porttitor leo. Lacus sed viverra tellus in hac habitasse.Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Integer malesuada nunc vel risus commodo. Neque aliquam vestibulum morbi blandit cursus risus.",
    "grades": "[{\"name\":\"Grade 9\",\"short_name\":\"9\"},{\"name\":\"Grade 10\",\"short_name\":\"10\"},{\"name\":\"Grade 11\",\"short_name\":\"11\"},{\"name\":\"Grade 12\",\"short_name\":\"12\"},{\"name\":\"Adult\",\"short_name\":\"AD\"}]"
}, {
    "name": "Test Entity 2",
    "about": "Blah blah blah"
}, {
    "name": "Test Entity 3"
}]

Я попытался обернуть внутреннюю SELECTоператоры с JSON_QUERY, как предложено в следующей ссылке, но это не имело никакого эффекта.

Ref: Как мне не допустить, чтобы FOR JSON PATH избегал результатов запроса?

Запрос с помощью функции обтекания JSON_QUERY

SELECT 
    entity.name AS name,
    JSON_QUERY((
    SELECT
        grade_translation.name,
        grade_translation.short_name
    FROM
        entity_grades,
        grade,
        grade_translation,
        language

    WHERE
         entity.id = entity_grades.entity_id
         AND entity_grades.grade_id = grade.id
         AND grade.id = grade_translation.non_translated_id
         AND grade_translation.language_id = language.id
         AND language.short_name = 'en'

    ORDER BY
        entity_grades.[order]

    FOR JSON PATH
    )) AS grades
FROM entity
LEFT JOIN entity_translation ON entity_translation.non_translated_id = entity.id
LEFT JOIN language ON language.id = entity_translation.language_id
WHERE language.short_name = 'en'

UNION

SELECT 
    entity.name AS name,
    JSON_QUERY((
    SELECT
        grade_translation.name,
        grade_translation.short_name
    FROM
        entity_grades,
        grade,
        grade_translation,
        language

    WHERE
         entity.id = entity_grades.entity_id
         AND entity_grades.grade_id = grade.id
         AND grade.id = grade_translation.non_translated_id
         AND grade_translation.language_id = language.id
         AND language.short_name = 'en'

    ORDER BY
        entity_grades.[order]

    FOR JSON PATH
    )) AS grades
FROM entity
LEFT JOIN entity_translation ON entity_translation.non_translated_id = entity.id
LEFT JOIN language ON language.id = entity_translation.language_id
WHERE entity.id NOT IN (SELECT DISTINCT entity_translation.non_translated_id FROM entity_translation)
FOR JSON PATH

Есть ли что-нибудь еще, что я могу попытаться вернуть в правильном формате JSON из этого стиля запроса?Может кто-нибудь объяснить, является ли это особенность или ошибка?

1 Ответ

0 голосов
/ 04 апреля 2019

Я решил это, полностью исключив СОЮЗ.В этом случае это было так же просто, как добавить WHERE … OR language.short_name IS NULL к первому запросу.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...