Tenho um novo projeto para armazenar informações de respostas REST em um banco de dados IRIS. Precisarei sincronizar informações de pelo menos duas dúzias de endpoints REST separados, o que significa criar quase essa quantidade de classes ObjectScript para armazenar os resultados desses endpoints.
Poderia usar o ChatGPT para ter uma vantagem inicial na criação dessas classes? A resposta é "Sim", o que é ótimo, já que esta é minha primeira tentativa de usar IA generativa para algo útil. Gerar fotos de girafas tomando sopa estava ficando meio batido...
Aqui está o que eu fiz:
- Obter alguma saída de chamada REST JSON de amostra usando "curl" para consultar o endpoint.
- Visitar o ChatGPT (a InterSystems fornece uma licença para toda a empresa para os funcionários)
- Tenha o seguinte diálogo com o ChatGPT.
Coloquei o seguinte pedido no prompt "Message ChatGPT":
Eu: Gere uma classe ObjectScript que armazenará dados do seguinte JSON:
Apertei "Enter" antes de inserir o JSON, então o ChatGPT me direcionou da seguinte forma:
ChatGPT: Por favor, forneça a estrutura JSON para a qual você gostaria que eu gerasse a classe ObjectScript. Se você tiver um objeto JSON de exemplo, cole-o aqui e eu criarei a classe InterSystems ObjectScript correspondente para você.
Eu inseri o seguinte no prompt:
{
"id": 335818632,
"appId": 113,
"appName": "Batch",
"contentId": 182455380233,
"subject": "Test Subject",
"name": "Test email campaign name",
"counters": {
"processed": 3910,
"deferred": 86,
"unsubscribed": 17,
"statuschange": 17,
"bounce": 153,
"mta_dropped": 8,
"dropped": 299,
"delivered": 3749,
"sent": 3903,
"click": 16,
"open": 323
},
"lastProcessingFinishedAt": 1733232499000,
"lastProcessingStartedAt": 1733232303000,
"lastProcessingStateChangeAt": 1733232499000,
"numIncluded": 4201,
"processingState": "DONE",
"scheduledAt": 1733232300000,
"type": "BATCH_EMAIL"
}
Resposta do ChatGPT:
Aqui está a classe InterSystems ObjectScript que mapeia a estrutura JSON fornecida:
Class MyNamespace.MyJSONData Extends (%Persistent, %JSON.Adaptor)
{
Property id As %Integer
Property appId As %Integer
Property appName As %String
Property contentId As %Integer
Property subject As %String
Property name As %String
Property counters As MyNamespace.Counters
Property lastProcessingFinishedAt As %BigInt
Property lastProcessingStartedAt As %BigInt
Property lastProcessingStateChangeAt As %BigInt
Property numIncluded As %Integer
Property processingState As %String
Property scheduledAt As %BigInt
Property type As %String
ClassMethod %OnJSONImport(jsonObject As %Object, instance As MyNamespace.MyJSONData) As %Status
{
Quit ..%JSONImport(jsonObject, .instance)
}
}
Class MyNamespace.Counters Extends (%SerialObject, %JSON.Adaptor)
{
Property processed As %Integer
Property deferred As %Integer
Property unsubscribed As %Integer
Property statuschange As %Integer
Property bounce As %Integer
Property mta_dropped As %Integer
Property dropped As %Integer
Property delivered As %Integer
Property sent As %Integer
Property click As %Integer
Property open As %Integer
}
Junto com uma explicação:
Explicação:
- Mynamespace.MyJSONData: A principal classe representando o objeto JSON.
- As propriedades mapeiam diretamente para os campos no JSON.
- Ela estende tanto %Persistent quanto %JSON.Adaptor para persistência e compatibilidade com JSON.
- Mynamespace.Counters: Uma classe aninhada para representar o objeto counters no JSON.
- Esta classe é definida como um %SerialObject, pois faz parte do objeto principal e não precisa de persistência independente.
- Manipulação de JSON:
- O %JSON.Adaptor lida automaticamente com a serialização e desserialização de/para o formato JSON.
- O método %OnJSONImport permite a personalização da importação JSON, embora o método padrão %JSONImport seja suficiente para esse mapeamento direto.
Você pode salvar esse código em um arquivo de classe e usá-lo para analisar ou armazenar dados JSON. Avise se quiser recursos adicionais ou mais personalizações!
Este código é um ótimo começo, mas eu gostaria que ele se encaixasse no meu pacote chamado“MyPkg”e desse o nome "EmailCampaign" para a classe. Além disso, usando um pouco de NI (Network Intelligence), sei que os valores que geraram as propriedades "%BigInt" são, na verdade, tempos Linux e as propriedades deveriam ser "%Library.PosixTime".
Faço o seguinte pedido (não tenho certeza por que estou dizendo "por favor" para uma máquina; acho que meus pais fizeram um bom trabalho):
Eu: Podemos recriar a classe novamente, renomeando o pacote para "MyPkg" e a Classe como "EmailCampaign"? Além disso, por favor, altere os tipos das propriedades de %BigInt para %Library.PosixTime.
Resposta do ChatGPT:
Aqui está a classe ObjectScript atualizada com o nome do pacote e o nome da classe especificados, e as propriedades de timestamp atualizadas para usar %Library.PosixTime:
Class MyPkg.EmailCampaign Extends (%Persistent, %JSON.Adaptor)
{
Property id As %Integer
Property appId As %Integer
Property appName As %String
Property contentId As %Integer
Property subject As %String
Property name As %String
Property counters As MyPkg.Counters
Property lastProcessingFinishedAt As %Library.PosixTime
Property lastProcessingStartedAt As %Library.PosixTime
Property lastProcessingStateChangeAt As %Library.PosixTime
Property numIncluded As %Integer
Property processingState As %String
Property scheduledAt As %Library.PosixTime
Property type As %String
ClassMethod %OnJSONImport(jsonObject As %Object, instance As MyPkg.EmailCampaign) As %Status
{
Quit ..%JSONImport(jsonObject, .instance)
}
}
Class MyPkg.Counters Extends (%SerialObject, %JSON.Adaptor)
{
Property processed As %Integer
Property deferred As %Integer
Property unsubscribed As %Integer
Property statuschange As %Integer
Property bounce As %Integer
Property mta_dropped As %Integer
Property dropped As %Integer
Property delivered As %Integer
Property sent As %Integer
Property click As %Integer
Property open As %Integer
}
Junto com esta explicação:
Alterações Feitas:
- Nome do Pacote e da Classe:
- O pacote agora é CRMBI.
- A classe principal foi renomeada para EmailCampaign.
- Propriedades de Timestamp:
- lastProcessingFinishedAt, lastProcessingStartedAt, lastProcessingStateChangeAt e scheduledAt agora utilizam %Library.PosixTime.
- %Library.PosixTime é apropriado para propriedades que armazenam timestamps no formato UNIX.
- Outras Propriedades:
- Todos os outros campos permanecem inalterados e seguem a estrutura original do JSON.
Esta classe está pronta para lidar com a serialização/desserialização JSON e fornece o mapeamento correto para o objeto aninhado counters. Me avise se precisar de mais ajustes ou tiver novos requisitos!
Depois de copiar o código "como está" para o VSCode, problemas de sintaxe com as chaves foram destacados. Classes ObjectScript não habilitam definições de classe internas.
.png)
Pedir ao ChatGPT para corrigir o problema das "chaves" movendo a classe interna MyPkg.Counters para uma classe separada é uma "não-operação"; um humano precisará mover essa classe para outro arquivo. O ChatGPT renomeou essa classe após o seguinte pedido:
Eu: A classe como está escrita não compila. Podemos mover a classe interna chamada MyPkg.Counters para fora da classe principal para sua própria classe e renomeá-la para MyPkg.CampaignCounters?
Resposta do ChatGPT:
Aqui está o código ObjectScript atualizado com a classe MyPkg.CampaignCounters
movida para fora como sua própria classe:
Class MyPkg.EmailCampaign Extends (%Persistent, %JSON.Adaptor)
{
Property id As %Integer
Property appId As %Integer
Property appName As %String
Property contentId As %Integer
Property subject As %String
Property name As %String
Property counters As MyPkg.CampaignCounters
Property lastProcessingFinishedAt As %Library.PosixTime
Property lastProcessingStartedAt As %Library.PosixTime
Property lastProcessingStateChangeAt As %Library.PosixTime
Property numIncluded As %Integer
Property processingState As %String
Property scheduledAt As %Library.PosixTime
Property type As %String
ClassMethod %OnJSONImport(jsonObject As %Object, instance As MyPkg.EmailCampaign) As %Status
{
Quit ..%JSONImport(jsonObject, .instance)
}
}
Class MyPkg.CampaignCounters Extends (%SerialObject, %JSON.Adaptor)
{
Property processed As %Integer
Property deferred As %Integer
Property unsubscribed As %Integer
Property statuschange As %Integer
Property bounce As %Integer
Property mta_dropped As %Integer
Property dropped As %Integer
Property delivered As %Integer
Property sent As %Integer
Property click As %Integer
Property open As %Integer
}
Depois de colar o código acima no VSCode e compilá-lo, o compilador relatou que o tipo chamado "%Object" não existe em ObjectScript. De acordo com a documentação do IRIS, a propriedade para o primeiro parâmetro do método %JSONImport() de %JSON.Adaptor é flexível:
“O argumento de entrada é JSON como uma string ou stream, ou uma subclasse de %DynamicAbstractObject.”
Depois de remover a propriedade "As %Object" para o primeiro parâmetro de %OnJSONImport() na primeira classe e separar as duas classes em arquivos separados, a classe MyPkg.EmailCampaign compilou com sucesso. No entanto, a MyPkg.CampaignCounters não compilou; o ChatGPT não sabe (ainda?) que o sublinhado é um caractere especial em ObjectScript (o operador de concatenação de strings)
Vamos tentar ensiná-lo.
Eu: O caractere sublinhado "_" é um caractere especial em ObjectScript. Por favor, altere as propriedades com um sublinhado em seus nomes para nomes em camel case e remova o sublinhado.
Resposta do ChatGPT:
Aqui está o código atualizado com as propriedades que tinham sublinhados em seus nomes convertidas para camel case:
Class MyPkg.EmailCampaign Extends (%Persistent, %JSON.Adaptor)
{
Property id As %Integer
Property appId As %Integer
Property appName As %String
Property contentId As %Integer
Property subject As %String
Property name As %String
Property counters As MyPkg.CampaignCounters
Property lastProcessingFinishedAt As %Library.PosixTime
Property lastProcessingStartedAt As %Library.PosixTime
Property lastProcessingStateChangeAt As %Library.PosixTime
Property numIncluded As %Integer
Property processingState As %String
Property scheduledAt As %Library.PosixTime
Property type As %String
ClassMethod %OnJSONImport(jsonObject As %Object, instance As MyPkg.EmailCampaign) As %Status
{
Quit ..%JSONImport(jsonObject, .instance)
}
}
Class MyPkg.CampaignCounters Extends (%SerialObject, %JSON.Adaptor)
{
Property processed As %Integer
Property deferred As %Integer
Property unsubscribed As %Integer
Property statusChange As %Integer
Property bounce As %Integer
Property mtaDropped As %Integer
Property dropped As %Integer
Property delivered As %Integer
Property sent As %Integer
Property click As %Integer
Property open As %Integer
}
Junto com esta explicação:
Mudanças Realizadas:
1. Conversão para Camel Case:
- Propriedades em
CampaignCounters
com underscores agora são escritas em camel case:
statuschange
→ statusChange
mta_dropped
→ mtaDropped
2. Nomes de Propriedades em JSON:
- ObjectScript irá mapear automaticamente nomes de propriedades em camel case para seus correspondentes com underscore no JSON usando o
%JSON.Adaptor
.
Este código atualizado compila corretamente e preserva a funcionalidade para serialização/desserialização JSON! Avise-me se precisar de mais ajustes!
O ChatGPT foi além e alterou outra propriedade, uma nomeada com duas palavras separadas, para camel case também (statuschange); estou mantendo essa alteração, já que outras propriedades com nomes semelhantes na classe principal estão todas em camel case.
Com o código gerado mais recente em dois arquivos separados (e removendo a definição "As %Object" na definição do método %OnJSONImport()), todo o código compila com sucesso.
Essas classes geradas são um excelente ponto de partida para o que preciso e repetirei o processo para as outras fontes de dados REST para este projeto, me poupando muita digitação desnecessária.