Artigo
· 14 hr atrás 5min de leitura

JSON2Class, o conversor de JSON para ObjectScript que você sempre quis

Quantas vezes você teve que receber ou gerar um JSON e desejou poder trabalhar nele usando DTLs sem ter que lidar com DynamicObjects tentando lembrar o nome de cada campo? Você quer dividir e tornar seu arquivo JSON gigante mais digerível?

No meu caso, nunca, mas pensei que alguém poderia achar útil ter um recurso que captura seu JSON e o divide em uma série de classes ObjectScript com as quais você pode trabalhar de forma mais fácil e conveniente.

Pois bem... contemplem o JSON2Class em toda a sua glória!

Como o JSON2Class funciona?

É muito simples: ele aproveita os recursos do Embedded Python para fatiar e analisar seu JSON e gerar as classes associadas. Essas classes geradas serão de dois tipos:

  • %Persistent: para a classe principal ou raiz.
  • %SerialObject: para todas as subclasses que serão anexadas à principal.

Para fazer isso, ele leva em consideração os seguintes pontos:

Palavras reservadas

Nem todo nome de propriedade que vem no seu JSON é aceitável, então ele será modificado adicionando ao final do nome JSON, de modo que " language" se tornará " languageJSON".

Caracteres especiais

Caracteres especiais como "_" também são  removidos, então "patient_name" passará a ser chamado de "patientname".

%JSONFIELDNAME

Para evitar que a classe mude de nome quando for convertida de volta para JSON, o atributo %JSONFIELDNAME foi adicionado às propriedades cujos nomes são modificados, permitindo manter o rótulo original ao exportá-lo para JSON.

Gerando as classes

Toda a funcionalidade está contida na classe Utils.JSON2Class  , e para invocar o processo de geração temos o seguinte método:

ClassMethod Convert(
    json As %String,
    basePackage As %String = "App.Model",
    rootClassName As %String = "Root",
    outDir As %String = "/shared/generated"
) As %String

Vamos analisar os atributos do ClassMethod:

  • json: Este será nosso JSON modelo que queremos gerar.
  • basePackage: O pacote no qual todas as classes serão implementadas.
  • rootClassName: O nome da classe persistente que atuará como a raiz.
  • outDir: O diretório local onde os arquivos de classe serão gerados.

Exemplo:

Começamos com um JSON típico, como um recurso FHIR do tipo patient:

{
	"resourceType": "Patient",
	"id": "example",
	"identifier": [
		{
			"use": "usual",
			"type": {
				"coding": [
					{
						"system": "http://terminology.hl7.org/CodeSystem/v2-0203",
						"code": "MR"
					}
				]
			},
			"system": "urn:oid:1.2.36.146.595.217.0.1",
			"value": "12345",
			"period": {
				"start": "2001-05-06"
			},
			"assigner": {
				"display": "Acme Healthcare"
			}
		}
	],
	"active": true,
	"name": [
		{
			"use": "official",
			"family": "Chalmers",
			"given": [
				"Peter",
				"James"
			]
		},
		{
			"use": "usual",
			"given": [
				"Jim"
			]
		},
		{
			"use": "maiden",
			"family": "Windsor",
			"given": [
				"Peter",
				"James"
			],
			"period": {
				"end": "2002"
			}
		}
	],
	"telecom": [
		{
			"use": "home"
		},
		{
			"system": "phone",
			"value": "(03) 5555 6473",
			"use": "work",
			"rank": 1
		},
		{
			"system": "phone",
			"value": "(03) 3410 5613",
			"use": "mobile",
			"rank": 2
		},
		{
			"system": "phone",
			"value": "(03) 5555 8834",
			"use": "old",
			"period": {
				"end": "2014"
			}
		}
	],
	"gender": "male",
	"birthDate": "1974-12-25",
	"_birthDate": {
		"extension": [
			{
				"url": "http://hl7.org/fhir/StructureDefinition/patient-birthTime",
				"valueDateTime": "1974-12-25T14:35:45-05:00"
			}
		]
	},
	"deceasedBoolean": false,
	"address": [
		{
			"use": "home",
			"type": "both",
			"text": "534 Erewhon St\nPeasantVille, Rainbow, Vic3999",
			"line": [
				"534 Erewhon St"
			],
			"city": "PleasantVille",
			"district": "Rainbow",
			"state": "Vic",
			"postalCode": "3999",
			"period": {
				"start": "1974-12-25"
			}
		}
	],
	"contact": [
		{
			"relationship": [
				{
					"coding": [
						{
							"system": "http://terminology.hl7.org/CodeSystem/v2-0131",
							"code": "N"
						}
					]
				}
			],
			"name": {
				"family": "du Marché",
				"_family": {
					"extension": [
						{
							"url": "http://hl7.org/fhir/StructureDefinition/humanname-own-prefix",
							"valueString": "VV"
						}
					]
				},
				"given": [
					"Bénédicte"
				]
			},
			"additionalName": [
				{
					"use": "nickname",
					"given": [
						"Béné"
					]
				}
			],
			"telecom": [
				{
					"system": "phone",
					"value": "+33 (237) 998327"
				}
			],
			"address": {
				"use": "home",
				"type": "both",
				"line": [
					"534 Erewhon St"
				],
				"city": "PleasantVille",
				"district": "Rainbow",
				"state": "Vic",
				"postalCode": "3999",
				"period": {
					"start": "1974-12-25"
				}
			},
			"additionalAddress": [
				{
					"use": "work",
					"line": [
						"123 Smart St"
					],
					"city": "PleasantVille",
					"state": "Vic",
					"postalCode": "3999"
				}
			],
			"gender": "female",
			"period": {
				"start": "2012"
			}
		}
	],
	"managingOrganization": {
		"reference": "Organization/1"
	}
}

Vamos agora olhar para o objeto Root, que será nossa classe principal de paciente:

Vamos agora olhar para o objeto Root, que será nossa classe principal de paciente:

Class App.Model.Root Extends (%Persistent, %JSON.Adaptor)
{

Property resourceType As %String;
Property idJSON As %String(%JSONFIELDNAME = "id");
Property identifier As list Of App.Model.Root.Identifier;
Property active As %Boolean;
Property name As list Of App.Model.Root.Name;
Property telecom As list Of App.Model.Root.Telecom;
Property gender As %String;
Property birthDate As %String;
Property deceasedBoolean As %Boolean;
Property address As list Of App.Model.Root.Address;
Property contact As list Of App.Model.Root.Contact;
Property managingOrganization As App.Model.Root.ManagingOrganization;
}

Et voilà! Agora podemos armazenar nosso JSON como um objeto regular.

Próximos passos

Não é ruim poder gerar automaticamente as classes, mas seria interessante poder transformar automaticamente o JSON em uma instância das classes que criamos, levando em conta as particularidades dos nomes das propriedades.

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