Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Caché, Ensemble, DeepSee, MiniM, IRIS, GT.M Новый топик    Ответить
 Кодировка в REST  [new]
phomka
Member

Откуда:
Сообщений: 35
Здравствуйте, коллеги.

Столкнулись с проблемой при получении данных из REST запроса.

Дана JSON строка:
{"Param":"русские буквы"}

Из нее необходимо получить объект.
 $$$THROWONERROR(st,##class(%ZEN.Auxiliary.jsonProvider).%ConvertJSONToObject(%request.Content,,.obj,1)) 
 
obj.Param
 
На выводе:
фывфывфыв

Посмотрела в описании метода..о кодировке ни слова. Однако в методах обратного преобразования везде указана utf-8.
При передаче запроса от REST клиента, в заголовке Content-Type:"text/json; charset=utf-8"
Клиент на java, хотя не уверена, что это имеет значение.

У меня, к сожалению, нет идей как это исправить. Может кто-то уже работал с этими методами?
23 апр 14, 10:41    [15920718]     Ответить | Цитировать Сообщить модератору
 Re: Кодировка в REST  [new]
servit
Member

Откуда: г. Кишинёв, Республика Молдова
Сообщений: 3117
Блог
phomka,
 d $system.OBJ.DisplayError(##class(%ZEN.Auxiliary.jsonProvider).%ConvertJSONToObject("{""Param"":""русские буквы""}",,.obj,$$$YES))
 
obj.Param
Результат:

USER>^test
русские буквы

Проверьте содержимое
  • %request.Content
  • %request.ContentType
  • %request.CharSet
23 апр 14, 11:42    [15921199]     Ответить | Цитировать Сообщить модератору
 Re: Кодировка в REST  [new]
EvLaUy
Member

Откуда: Москва
Сообщений: 2189
phomka,
в подобных ситуациях лучшими друзьями становятся функции extract, ascii и char. Вам почему-то в кодировке UTF-8 пришла строка "фывфывфыв". Вы именно такую задавали? Нужно пройтись по ней extract'ом и для каждого символа посмотреть его код функцией ascii. У Вас будет что-то типа 209, 148, 209, 155, 208, 178 и т.д. А потом набрать в терминале строку русским буквами, сохранить ее в какой-то переменной, убедиться, что райтом она нормально отображается и посмотреть коды ее байт. Затем сравнить и попытаться объяснить разницу. Когда-то в особо тяжелых случаях я на основании этого анализа просто писал свой конвертор да и всё, но сейчас, думаю, в таком радикальном решении уже нет необходимости, ибо в Cache уже достаточно "рулей", которые Вам указал servit, чтобы решить проблему "малой кровью".
23 апр 14, 11:58    [15921352]     Ответить | Цитировать Сообщить модератору
 Re: Кодировка в REST  [new]
phomka
Member

Откуда:
Сообщений: 35
  • 4@%CSP.BinaryStream
  • text/json
  • UTF-8

    И они одинаковы, если я просто вставлю запрос в виде строки, или если получу от клиента. А выводятся по разному.
  • 23 апр 14, 12:13    [15921501]     Ответить | Цитировать Сообщить модератору
     Re: Кодировка в REST  [new]
    phomka
    Member

    Откуда:
    Сообщений: 35
    EvLaUy, да, строка там была другая - немного схалтурила...

    Воспользуюсь советом, отпишусь что получится.
    23 апр 14, 12:17    [15921534]     Ответить | Цитировать Сообщить модератору
     Re: Кодировка в REST  [new]
    phomka
    Member

    Откуда:
    Сообщений: 35
    EvLaUy,

    Хотя, получается, что проблема в %request.Content...
    23 апр 14, 12:23    [15921586]     Ответить | Цитировать Сообщить модератору
     Re: Кодировка в REST  [new]
    EvLaUy
    Member

    Откуда: Москва
    Сообщений: 2189
    Мне сложно сказать в чем проблема, у меня сейчас нет под рукой cache. Может быть, всё дело в том, как Вы задаете эту строку перед отправкой запроса? Если это Java, попробуйте задать ее в кодах utf-8. Что-то типа "\u0112\u0130\u0141\u14f", это кажется строка "Вася". Посмотрите, поможет ли. Во всяком случае, будет уверенность, что она уходит именно в кодировке utf-8.
    23 апр 14, 12:33    [15921688]     Ответить | Цитировать Сообщить модератору
     Re: Кодировка в REST  [new]
    EvLaUy
    Member

    Откуда: Москва
    Сообщений: 2189
    "\u0112\u0130\u0141\u014f"
    23 апр 14, 12:34    [15921699]     Ответить | Цитировать Сообщить модератору
     Re: Кодировка в REST  [new]
    servit
    Member

    Откуда: г. Кишинёв, Республика Молдова
    Сообщений: 3117
    Блог
    phomka
    4@%CSP.BinaryStream
    То, что это поток, и так понятно: каково его содержимое?

    ##class(%ZEN.Auxiliary.jsonProvider).%ConvertJSONToObject("4@%CSP.BinaryStream",,.obj,1)

    выдаст ошибку

    ОШИБКА #5001: Expected { at start of JSON text.

    , так же как и

    ##class(%ZEN.Auxiliary.jsonProvider).%ConvertJSONToObject(%request.Content,,.obj,1)

    должен выдать эту же ошибку, так как на вход метода ожидается строка, а Вы передаёте поток.
    23 апр 14, 13:00    [15921938]     Ответить | Цитировать Сообщить модератору
     Re: Кодировка в REST  [new]
    Александр Коблов
    Member

    Откуда: Краснодар, Москва
    Сообщений: 240
    Насколько я понимаю, сейчас %request.Content игнорирует заголовок ContentType.
    То есть вам нужно самой смотреть значение %request.Content.ContentType и в зависимости от charset преобразовывать строку во внутренний формат Caché.

    Например, из UTF-8 можно преобразовать следующей командой (первый 100 знаков):
    Set str $ZCVT(%request.Content.Read(100),"I","UTF8")

    или таким образом:
    if $isobject(%request.Content{
       
    Set %request.Content.Attributes("CharEncoding")="UTF8"
       
    Set stream=##class(%IO.MetaCharacterStream).%New(%request.Content)
       
    Set ^lastRequestContent = stream.Read()
    Заметьте, что %request.Content типа %CSP.BinaryStream, то есть это бинарный, а не символьный поток.

    ##class(%ZEN.Auxiliary.jsonProvider).%ConvertJSONToObject может принимать на вход и строки и потоки.
    http://docs.intersystems.com/cache20141/csp/documatic/%CSP.Documatic.cls?PAGE=CLASS&LIBRARY=%SYS&CLASSNAME=%ZEN.Auxiliary.jsonProvider#%ConvertJSONToObject
    23 апр 14, 13:44    [15922447]     Ответить | Цитировать Сообщить модератору
     Re: Кодировка в REST  [new]
    servit
    Member

    Откуда: г. Кишинёв, Республика Молдова
    Сообщений: 3117
    Блог
    phomka,

    USER>w $zcvt($zcvt("фывфывфыв","O","CP1251"),"I","UTF8")
    фывфывфыв

    соответственно

    USER>w $zcvt($zcvt("фывфывфыв","O","UTF8"),"I","CP1251")
    фывфывфыв

    Итого где-то происходит конвертация в кодировку Windows-1251.

    PS: какую версию Caché используете: Unicode или 8-битную?
    23 апр 14, 13:45    [15922454]     Ответить | Цитировать Сообщить модератору
     Re: Кодировка в REST  [new]
    servit
    Member

    Откуда: г. Кишинёв, Республика Молдова
    Сообщений: 3117
    Блог
    Александр Коблов
    %ConvertJSONToObject может принимать на вход и строки и потоки.
    Ценное замечание: по сигнатуре метода и соответственно подсказке кода этого и не скажешь.
    23 апр 14, 13:57    [15922571]     Ответить | Цитировать Сообщить модератору
     Re: Кодировка в REST  [new]
    phomka
    Member

    Откуда:
    Сообщений: 35
    Коллеги, спасибо!
    Я вчера все прочитала и все сделала.
    Очень ценные советы.

    servit, использую 8-битную версию.
    24 апр 14, 04:08    [15926468]     Ответить | Цитировать Сообщить модератору
    Между сообщениями интервал более 1 года.
     Re: Кодировка в REST  [new]
    servit
    Member

    Откуда: г. Кишинёв, Республика Молдова
    Сообщений: 3117
    Блог
    phomka
    У меня, к сожалению, нет идей как это исправить.
    В будущих версиях можно будет включить автоматическую конвертацию тела запроса, а пока можно воспользоваться следующим кодом:
     If $IsObject(%request.Content),$zcvt(%request.Content.ContentType,"L")["charset=utf-8" {
      
    Set contentTmp=%request.Content.%ConstructClone(-1)
      
    Set contentTmp.Attributes("CharEncoding")="UTF8"

      ; сохраняем переданные атрибуты
      
    Merge attr=%request.Content.Attributes
      Do 
    %request.Content.Clear()
      
    Merge %request.Content.Attributes=attr
      
      
    Do %request.Content.CopyFrom(##class(%IO.MetaCharacterStream).%New(contentTmp))
     
    }
    , который лучше поместить в метод OnPreDispatch.

    Далее работаете с %request.Content как обычно.

    PS: спасибо Александр Коблов за наводку на %IO.MetaCharacterStream.
    8 июл 15, 09:09    [17865680]     Ответить | Цитировать Сообщить модератору
     Re: Кодировка в REST  [new]
    servit
    Member

    Откуда: г. Кишинёв, Республика Молдова
    Сообщений: 3117
    Блог
    servit
    В будущих версиях можно будет включить автоматическую конвертацию тела запроса
    В 2016.1 уже добавили эту возможность, проверил - работает.
    13 ноя 15, 10:48    [18410813]     Ответить | Цитировать Сообщить модератору
    Все форумы / Caché, Ensemble, DeepSee, MiniM, IRIS, GT.M Ответить