Artigo
· 16 hr atrás 9min de leitura

Gerando uma Classe ObjectScript a partir de uma Resposta JSON Usando o ChatGPT.

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:

  1. 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.
  2. 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.
  3. 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 chamadoMyPkge 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:

  1. Nome do Pacote e da Classe:
    • O pacote agora é CRMBI.
    • A classe principal foi renomeada para EmailCampaign.
  2. Propriedades de Timestamp:
    • lastProcessingFinishedAt, lastProcessingStartedAt, lastProcessingStateChangeAt e scheduledAt agora utilizam %Library.PosixTime.
    • %Library.PosixTime é apropriado para propriedades que armazenam timestamps no formato UNIX.
  3. 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.

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:
    • statuschangestatusChange
    • mta_droppedmtaDropped

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.

Discussão (0)1
Entre ou crie uma conta para continuar