powered by simpleCommunicator - 2.0.37     © 2025 Programmizd 02
Форумы / Caché, Ensemble, DeepSee, MiniM, IRIS, GT.M [игнор отключен] [закрыт для гостей] / JSON to Object (ID)
25 сообщений из 30, страница 1 из 2
JSON to Object (ID)
    #39205487
Блок А.Н.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть задача открыть объект, преобразовать его в JSON, как-то его поправить и обратно из JSON сохранить.
В этот момент у меня возникает проблема, при преобразовании JSON в объект методом ##class(%ZEN.Auxiliary.jsonProvider).%ConvertJSONToObject() теряется id, объект получается как будто новый. Соответственно, при сохранении он и ведет себя как новый.
Есть ли возможность при конвертации json в объект штатными средствами подхватывать и изменять уже существующие сохраненные объекты? Как вы разрешали для себя такую ситуацию?

Пример могу соорудить, но мне кажется, что те, кто с этим сталкивался, и так в курсе проблемы.
...
Рейтинг: 0 / 0
JSON to Object (ID)
    #39205716
О-О-О
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Блок А.Н.,

Зачем так сложно.
Преобразовать, затем самому подправить, затем назад преобразовать?
Смысл вообще не понятен.
...
Рейтинг: 0 / 0
JSON to Object (ID)
    #39205722
servit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Блок А.Н.Есть задача открыть объект, преобразовать его в JSON, как-то его поправить и обратно из JSON сохранить.
Есть ли возможность при конвертации json в объект штатными средствами подхватывать и изменять уже существующие сохраненные объекты? Как вы разрешали для себя такую ситуацию?Например:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
Class my.test Extends %Persistent
{

Property f As %Integer [ InitialExpression = 5 ];

ClassMethod Test(case = "")
{
  d ..%KillExtent()
  d ..%New().%Save()
  
  s obj=..%OpenId(1)
  w "До: f = ",obj.f,!
  
  if case="" {
    ; преобразовываем наш объект в объект JSON (тип %Object, не строка!)
    s json={"returnValue":obj}
    w "(test1) json = ",$classname(json),!
    
    s json.returnValue.f=3 ;меняем значение свойства
    
    ; преобразовываем JSON обратно в наш тип %RegisteredObject
    d obj.$compose(json)
  }else{
    ; преобразовываем наш объект в объект JSON (тип %Object, не строка!)
    s json=({}).$fromObject(obj)
    /*
    ; или так
    ; преобразовываем наш объект сначала в JSON-строку, потом в объект JSON (тип %Object)
    s json=({}).$fromJSON(obj.$toJSON())
    */

    w "(test2) json = ",$classname(json),!
    
    s json.f=3 ;меняем значение свойства

    ; преобразовываем JSON-объект обратно в наш тип %RegisteredObject
    d json.$compose(obj)
  }
  
  ;сохраняем как обычно
  d obj.%Save()
  k obj

  w "После: f = ",..%OpenId(1).f
}

}
Результат:

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
USER>d ##class(my.test).Test()
До: f = 5
(test1) json = %Library.Object
После: f = 3
USER>d ##class(my.test).Test(1)
До: f = 5
(test2) json = %Library.Object
После: f = 3
USER>
...
Рейтинг: 0 / 0
JSON to Object (ID)
    #39205725
servit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
О-О-ОБлок А.Н.,

Зачем так сложно.
Преобразовать, затем самому подправить, затем назад преобразовать?
Смысл вообще не понятен.Наверное потому, что этапБлок А.Н.Есть задача открыть объект, преобразовать его в JSON, как-то его поправить и обратно из JSON сохранить.должен будет происходить вне Caché?
...
Рейтинг: 0 / 0
JSON to Object (ID)
    #39205868
Блок А.Н.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
servit,

да, этап правки объекта должен проходить на клиенте в браузере. Мне показалось что json хороший способ передачи объектов каше в яваскрипт и обратно и что так все делают.

Пример не получилось скомпировать, у нас на рабочей версия каше 2014, у меня на компе стоит 2015.2, по-видимому, 2016 только вышла. Но все равно он не отражает суть того, что мне нужно.

Мне приходит из клиента некий json, включающий в себя в том числе и id, и мне нужно из него создать объект, причем, если указан id, заменить хранимый объект в базе. В примере же мы открываем объект, и в него "заливаем" некий json. В моем случае я не знаю, какой объект мне открывать и по сути создаю его заново, но создать хочу уже с ID, чтобы при сохранении он затер существующий.

Пока я вижу два пути, и оба они мне очень не нравятся:
- превратить json в %ZEN.proxyObject, посмотреть, если ли там ID, если есть, то открыть объект и присвоить в него поля из %ZEN.ProxyObject
- написать свой парсер.
...
Рейтинг: 0 / 0
JSON to Object (ID)
    #39206293
servit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Блок А.Н.Но все равно он не отражает суть того, что мне нужно.
А теперь?Пример для 2016.2
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
Class my.test Extends %Persistent
{

Property f As %Integer [ InitialExpression = 5 ];

/// d ##class(my.test).Test()
ClassMethod Test()
{
  #define JSONUpsert(%json) $s(%json."_id"="":$system.OBJ.New(%json."_class"),1:$system.OBJ.OpenId(%json."_class",%json."_id"))
  
  d ..%KillExtent()
  d ..%New().%Save()
  
  s obj1=..%OpenId(1) ; или ..%New()
  
  ; отправляем клиенту JSON-строку
  w "<- f = ",obj1.f,!,"<- json = ",obj1.$toJSON(),!!
  
  ; меняем наш JSON где-то на стороне и получаем его обратно. 
  ; допустим мы получили это
  
  s jsonStr="{""_class"":""my.test"",""_id"":""1"",""f"":3}"
  w "-> json = ",jsonStr,!
  
  ; преобразовываем JSON-строку в JSON-объект
  s json=({}).$fromJSON(jsonStr)
  
  ; создаём или открываем объект нужного типа (и с нужным ID)
  s obj2=$$$JSONUpsert(json)
  ; заполняем его данными из JSON-объекта 
  d json.$compose(obj2)

  ;сохраняем как обычно
  d obj2.%Save()
  k obj2

  w "-> f = ",..%OpenId(1).f
}

/// Дополнительно к встроенному поведению, также присваиваем значения свойствам _class и _id
Method %ToDynamicObject(
  target As %Object = "",
  ignoreUnknown = 0) [ ServerOnly = 1 ]
{
  s:target="" target = {}
  s target."_class" = $classname() 
  s target."_id" = ..%Id()
  d ##super(.target,.ignoreUnknown)
}

}
Результат:

Код: plaintext
1.
2.
3.
4.
5.
6.
USER>d ##class(my.test).Test()
<- f = 5
<- json = {"_class":"my.test","_id":"1","f":5}
 
-> json = {"_class":"my.test","_id":"1","f":3}
-> f = 3
USER>
Для более старых версий легко можно сделать только отправку:
Код: plaintext
1.
 d ##class(%ZEN.Auxiliary.jsonProvider).%WriteJSONStreamFromObject(.stream,..%OpenId(1),,,1,"aelqoc")
 w "<- json = ",stream.Read(),!
С заполнением уже открытого объекта из JSON придётся писать велосипед.
...
Рейтинг: 0 / 0
JSON to Object (ID)
    #39206340
Блок А.Н.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
servit,

Значит, велосипед, жаль.
И даже в новых версиях без костылька не взлетает :-(.
Спасибо.
...
Рейтинг: 0 / 0
JSON to Object (ID)
    #39206532
Блок А.Н.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Поправил ##class(%ZEN.Auxiliary.jsonProvider).%ConvertJSONToObject()
Совсем нехорошо, но проще всего. Писать свой парсер лень, да и безглючно я его не напишу. Скопировать код IS в свой класс можно, что что-то меня от этого тоже останавливает.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
Вместо

Set pObject = $classmethod(tClass,"%New")

теперь

s id = $G(tPropValues("_id"))
if id = "" 
{
 s pObject = $classmethod(tClass,"%New")
}
else 
{
 s pObject = $classmethod(tClass,"%OpenId",id)
}
...
Рейтинг: 0 / 0
JSON to Object (ID)
    #39270864
Блок А.Н.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
servit

Добрались руки до того, чтобы пощупать новые версии Каше.
Пытаюсь запустить ваш код - не получается.
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
USER>w $zv
Cache for Windows (x86-32) 2016.1.1 (Build 107U) Sat Jun 11 2016 19:32:35 EDT
USER>d ##class(my.test).Test()
До: f = 5
(test1) json = %Library.Object
 
    d obj.$compose(json)
    ^
<METHOD DOES NOT EXIST>zTest+11^my.test.1 *$compose,my.test
В какой версии появляются $compose, $fromObject? Вроде использую самую новую официально выпущенную на текущий момент
...
Рейтинг: 0 / 0
JSON to Object (ID)
    #39270866
Блок А.Н.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вообще смотрю я на это все и не понимаю.
Вроде бы все хорошо, сделали поддержку JSON, только %Object живет своей жизнью, а все остальные классы своей и друг с другом не пересекаются. Наверное в этом бы какой-то смысл, может быть идеологическая чистота или еще что-нибудь такое, только зачем она нужна в этом случае? В одной пробирке две не смешивающиеся жидкости.

Я понимаю, что еще практически еще ни в чем не разобрался и в своей манере полез писать на форум, но первая эмоция именно такая - недоумение.
...
Рейтинг: 0 / 0
JSON to Object (ID)
    #39271113
servit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Блок А.Н.Пытаюсь запустить ваш код - не получается.Правильно не получается.
Будьте внимательны, я указал минимальную версию Caché для работы примера: 19006466 Блок А.Н.Вообще смотрю я на это все и не понимаю.
Вроде бы все хорошо, сделали поддержку JSON, только %Object живет своей жизнью, а все остальные классы своей и друг с другом не пересекаются.Это не так.
В версиях 2016.(2/3) интеграция JSON с SQL, объектами и "Caché Document Data Model", а также его производительность существенно улучшены и это не предел. Работа ведётся и дальше: кое какие улучшения запланировали на 2016.4/2017.1, а некоторые уже решили в 2016.3.
...
Рейтинг: 0 / 0
JSON to Object (ID)
    #39271374
Блок А.Н.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
servit,

понятно, спасибо. Получается, пока без костылей и самоделок не обойтись даже на новых версиях. Значит ждем.
...
Рейтинг: 0 / 0
JSON to Object (ID)
    #39271593
servit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Блок А.Н.понятно, спасибо. Получается, пока без костылей и самоделок не обойтись даже на новых версиях. Значит ждем.Для хранения, извлечения, обновления непосредственно JSON-объектов добавили новую модель данных - Caché Document Data Model (сокращённо DocDM).
В которой можно индексировать данные для ускорения выборки, использовать готовый REST API, SQL и/или JSON Path Language, хранить любые JSON-объекты. Причём в этой модели необязательно, чтобы набор полей в коллекции "однотипных" экземпляров совпадал.
Вот небольшой пример с демонстрацией лишь некоторых возможностей:
Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
50.
51.
52.
s db = ##class(%DataModel.Document.Database).$getDatabase()

;удаляем данные от предыдущих тестов
d db.$dropCollection("test")

;получаем коллекцию наших объектов
s coll = db.$getCollection("test")

; сохраняем некий объект в БД
d coll.$insert({"id":1,"поле 1":"значение 1","a":true,"b":null}) 
; вставляем или обновляем другой объект в БД с documentID=2
d coll.$upsert(2,{"id":1,"поле 2":"значение 2","a":false,"b":"null"}) 

; отображаем содержимое нашей коллекции
d coll.$getAll().$toJSON()    

; выбираем один объект, где b is null и отображаем его (здесь вместо JSON Path Language можно использовать "обычный" SQL)
s rset=coll.$queryCollection(
        {"columns":[{"column":"b","path":"$.b"}],
         "restriction":"b is null",
         "limit":1})
w !!,"1)",!,rset.$toJSON()

; открываем объект c documentID=2 и отображаем его
s obj=coll.$get(2)
w !!,"2) ",obj.$toJSON(),!!

; меняем объект (можем добавить новые поля или удалить уже существующие)
s obj."новое поле 1"="новое значение 1"
d obj.$remove("id")

; обновляем его в БД
d coll.$replace(2,obj)
; отображаем текущее состояние нашей БД
d coll.$getAll().$toJSON()    

USER>d ^test
[
{"documentID":1,"documentVersion":1,"content":{"id":1,"поле 1":"значение 1","a":true,"b":null}},
{"documentID":2,"documentVersion":2,"content":{"id":1,"a":false,"b":"null","поле 2":"значение 2"}}
]
 
1)
[
{"_sourceID":1,"_sourceVersion":1,"content":{"id":1,"поле 1":"значение 1","a":true,"b":null}}
]
 
2) {"id":1,"a":false,"b":"null","поле 2":"значение 2"}
 
[
{"documentID":1,"documentVersion":1,"content":{"id":1,"поле 1":"значение 1","a":true,"b":null}},
{"documentID":2,"documentVersion":3,"content":{"a":false,"b":"null","поле 2":"значение 2","новое поле 1":"новое значение 1"}}
]
...
Рейтинг: 0 / 0
JSON to Object (ID)
    #39271760
Timur Safin
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
servit,

Тут такое дело.

Всё опять будет переделано, все системные методы выброшены и переименованные в обычные % методы (с "правильным", уже привычным соглашением об именах).

Ну т.е. не $push, а %Push, не $new а %New, не $getCollection а %GetCollection. Более подробные детали этой переделки будут сообщены дополнительно (в community).
...
Рейтинг: 0 / 0
JSON to Object (ID)
    #39271809
servit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Timur SafinВсё опять будет переделаноЭто нормально для FieldTest. Более того, я думаю - не последняя. Главное, что функционал останется.
...
Рейтинг: 0 / 0
JSON to Object (ID)
    #39271818
Фотография DAiMor
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
servitTimur SafinВсё опять будет переделаноЭто нормально для FieldTest. Более того, я думаю - не последняя. Главное, что функционал останется.Одна версия уже успела уйти в релиз, так что это уже может быть проблемой, у меня уже один проект в продакшене с $
...
Рейтинг: 0 / 0
JSON to Object (ID)
    #39271844
servit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
DAiMorОдна версия уже успела уйти в релиз, так что это уже может быть проблемой, у меня уже один проект в продакшене с $Что касаетсяTimur Safin<..>не $getCollection а %GetCollection<..>, то это DocDM, который пока не в релизе.
А остальные методы можно обернуть в макросы с условной компиляцией, поставив в зависимость текущую версию Caché. eduard93 пошёл именно этим путём .

PS: согласен, нехорошо менять API после релиза. Это тот случай, когда: "Семь раз отмерь, один - отрежь." ("Look before you leap")
...
Рейтинг: 0 / 0
JSON to Object (ID)
    #39272338
doublefint
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Timur Safin все системные методы выброшены и переименованные в обычные % методы (с "правильным", уже привычным соглашением об именах) Да!!! :)
...
Рейтинг: 0 / 0
JSON to Object (ID)
    #39272784
Блок А.Н.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть еще момент, который меня смущал (если у меня опять в голове все не перепуталось, и я действительно правильно помню то, работал экспорт в 2014):
Каше объекты, на которые есть ссылки, превращает в дочерний узел JSON. Это не всегда хорошо, так как в некоторых случаях можно высосать через объект полбазы. Можно ограничивать глубину вложенности, но это не то.
На мой взгляд, нужно при выводе ссылок на объекты выводить его ID (если возможно определить), либо вообще регулировать этот вопрос параметрами поля. При разборе JSON тоже полезно уметь понимать и принимать не полную структуру объекта, а его ID.

Что-то в этом направлении делается?
...
Рейтинг: 0 / 0
JSON to Object (ID)
    #39272792
servit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Блок А.Н.Каше объекты, на которые есть ссылки, превращает в дочерний узел JSON. Это не всегда хорошо, так как в некоторых случаях можно высосать через объект полбазы. Можно ограничивать глубину вложенности, но это не то.
На мой взгляд, нужно при выводе ссылок на объекты выводить его ID (если возможно определить), либо вообще регулировать этот вопрос параметрами поля. При разборе JSON тоже полезно уметь понимать и принимать не полную структуру объекта, а его ID.

Что-то в этом направлении делается?Обязательно.Пример для 2016.3
Код: plaintext
SAMPLES>w ##class(Sample.Person).%OpenId(101).$toJSON()
{"$CLASSNAME":"Sample.Employee","$REFERENCE":"101","Age":22,"Company":{"$CLASSNAME":"Sample.Company","$REFERENCE":"4"},"DOB":56006,"FavoriteColors":["Red","Black"],"Home":{"City":"Reston","State":"WY","Street":"5572 Ash Avenue","Zip":79167},"Name":"Gore,David B.","Notes":{"$CLASSNAME":"%Stream.GlobalCharacter","content":["David used to work at DynaDyne.com as a(n) Assistant Director"]},"Office":{"City":"Islip","State":"MN","Street":"9434 First Drive","Zip":15857},"Picture":{"$CLASSNAME":"%Stream.GlobalBinary","$ERROR":"Mapping streams to %AbstractObject not currently supported"},"SSN":"118-21-3732","Salary":44260,"Spouse":{"$CLASSNAME":"Sample.Person","$REFERENCE":"16"},"Title":"Developer"}Если что-то в формате не устраивает, всегда можно переопределить пару callback-методов, пример которых также приводился выше ( 19006466 ).
...
Рейтинг: 0 / 0
JSON to Object (ID)
    #39272805
Блок А.Н.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
servit,

В формате не устраивает то, что в нем вообще нет ID. Соотвественно, переданный в JSON объект обратно в хранимый не преобразуешь. Если на внешнем уровне еще можно вручную прилепить ID, то на вложенных узлах что делать? Создавать новые объекты? А если это ссылка, например, на запись справочника? Сохранять в нем новую запись или не сохранять ссылку вообще?
Писать костыли на каждый класс при том, что сам механизм ущербен - как-то неправильно.

Ну и как я уже говорил, создание дочернего узла JSON для хранимого объекта, доступного по ссылке, не всегда нужно (и вообще, непонятно, нужно ли)
...
Рейтинг: 0 / 0
JSON to Object (ID)
    #39272813
Alexey Maslov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Блок А.Н.,

ИМХО, это общая проблема ссылочной целостности при обмене данными. Не побоитесь передавать ссылку на ID записи справочника? А вдруг "на той стороне" ID в базе по какой-то причине другие? Возможно, GUID или какой-то его "предметный" аналог подошёл бы лучше.

PS. Возможно, пишу тривиальные вещи, и я просто неправильно вас понял.
...
Рейтинг: 0 / 0
JSON to Object (ID)
    #39272830
Блок А.Н.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Alexey Maslov,

guid тоже может быть id, не вижу проблемы.
...
Рейтинг: 0 / 0
JSON to Object (ID)
    #39272868
servit
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Блок А.Н.В формате не устраивает то, что в нем вообще нет ID. Соотвественно, переданный в JSON объект обратно в хранимый не преобразуешь.Действительно, в формате нет ID, но есть его аналог - $REFERENCE, а также $CLASSNAME, поэтому "из коробки" всё есть для преобразования в обе стороны.
Или мы говорим о разных вещах?
...
Рейтинг: 0 / 0
JSON to Object (ID)
    #39272955
Блок А.Н.
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
servit есть его аналог - $REFERENCEИзвиняюсь, не по глазам.
В предыдущих версиях было вроде бы _id и _classname, поэтому искал что-то подобное.
...
Рейтинг: 0 / 0
25 сообщений из 30, страница 1 из 2
Форумы / Caché, Ensemble, DeepSee, MiniM, IRIS, GT.M [игнор отключен] [закрыт для гостей] / JSON to Object (ID)
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]