New post

検索

Article
· Jan 28 5m read

JSON2Class, the JSON to ObjectScript converter you've always wanted

How many times have you had to receive or generate a JSON and wished you could work on it using DTLs without having to deal with DynamicObjects trying to remember the name of each field? Do you want to break down and make your giant JSON file more digestible?

In my case, never, but I thought that someone might find it useful to have a feature that captures your JSON and breaks it down into a series of ObjectScript classes that you can work with more easily and conveniently.

Well then...behold JSON2Class in all its glory!

How does JSON2Class work?

It's very simple: it leverages Embedded Python's capabilities to slice and parse your JSON and generate the associated classes. These generated classes will be of two types:

  • %Persistent: for the main or root class.
  • %SerialObject: for all subclasses that will be attached to the main one.

To do this, it takes into consideration the following points:

Reserved words

Not just any property name that comes in your JSON is acceptable, so it will be modified by adding to the end of the JSON name, so that " language" will become " languageJSON".

Special characters

Special characters such as "_" are also  removed, so "patient_name" will now be called "patientname".

%JSONFIELDNAME

To prevent the class from changing its name when it is converted back to JSON, the %JSONFIELDNAME attribute has been added to the properties whose names are modified, allowing us to maintain the original label when exporting it to JSON.

Generating the classes

All the functionality is contained within the Utils.JSON2Class  class , and to invoke the generation process we have the following method:

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

Let's analyze the attributes of the ClassMethod:

  • json: This will be our template JSON that we want to generate.
  • basePackage: The package in which all the classes will be implemented.
  • rootClassName: The name of the persistent class that will act as the root.
  • outDir: The local directory where the class files will be generated.

Example:

We started with a typical JSON, such as a FHIR resource of type 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"
	}
}

Let's now look at the Root object, which will be our main patient class:

Let's now look at the Root object, which will be our main patient class:

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 voila! We can now store our JSON as a regular object.

Next steps

It's not bad to be able to automatically generate the classes, but it would be interesting to be able to automatically transform the JSON into an instance of the classes we have created, taking into account the particularities of the property names.

We'll leave it in the to-do pile

homer simpson sits on a couch next to a stack of papers and a can of duff beer

Discussion (0)1
Log in or sign up to continue
Article
· Jan 28 5m read

JSON2Class, el conversor de JSON a ObjectScript que siempre deseaste

¿Cuantas veces habéis tenido que recibir o generar un JSON y habéis añorado el poder trabajar sobre él haciendo uso de DTLs y sin tener que ir manejando DynamicObjects intentando recordar cual era el nombre de cada campo?

¿Deseas trocear y hacer más digerible tu gigantesco JSON?

En mi caso, nunca, pero he pensado que a alguien le podría resultar de utilidad una funcionalidad que capture tu JSON y lo descomponga en una serie de clases de ObjectScript con las que puedas trabajar de forma más cómoda y sencilla.

Pues bien...¡contemplad el JSON2Class en toda su gloria!

¿Cómo funciona JSON2Class?

Muy sencillo, aprovecha las capacidades de Embedded Python para trocear y analizar tu JSON y generar las clases asociadas al mismo. Estas clases generadas serán de dos tipos:

  • %Persistent: para la clase principal o root.
  • %SerialObject: para todas las subclases que colgarán de la principal.

Para ello tiene en consideración los siguientes puntos:

Palabras reservadas

No nos vale cualquier nombre de propiedad que venga en tu JSON, por lo que se modificará añadiendo al final del nombre JSON, de tal forma que "language" pasará a ser "languageJSON".

Carácteres especiales

También se eliminan los carácteres especiales como "_", por lo que "patient_name" pasará a denominarse "patientname".

%JSONFIELDNAME

Para evitar que a la hora de convertir nuevamente la clase a JSON se han añadido a las propiedades que ven modificados sus nombres el atributo %JSONFIELDNAME que nos permite mantener la etiqueta original cuando lo exportemos a JSON.

Generando las clases

Toda la funcionalidad se encuentra dentro de la clase Utils.JSON2Class y para invocar el proceso de generación disponemos del método:

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

Analicemos los atributos del ClassMethod:

  • json: será nuestro json de plantilla que queremos generar. 
  • basePackage: el package sobre el que se implementarán todas las clases. 
  • rootClassName: el nombre de la clase persistente que ejercerá de raíz.
  • outDir: directorio local donde se van a generar los ficheros de las clases.

Ejemplo:

Hemos partido de un JSON típico como sería un recurso FHIR de tipo paciente:

{
	"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"
	}
}

Y al ejecutar el conversor hemos obtenido las siguientes clases:

Veamos ahora el objeto Root, que será nuestra clase principal del 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 voila! Ya podemos almacenar nuestro JSON como un objeto al uso.

Siguientes pasos

No esta mal poder generar automáticamente las clases, pero será interesante poder transformar automáticamente el JSON a una instancia de las clases que hemos creado teniendo en cuenta las particularidades de los nombres de las propiedades.

Lo dejaremos en la pila de cosas por hacer.

homer simpson sits on a couch next to a stack of papers and a can of duff beer

Discussion (0)1
Log in or sign up to continue
Article
· Jan 28 2m read

Reseñas en Open Exchange - #63

Si uno de vuestros paquetes en OEX recibe una reseña, OEX os notificará únicamente sobre vuestro propio paquete. La valoración refleja la experiencia del revisor con el estado del paquete en el momento de la reseña.
Es como una “fotografía” del estado en ese momento y podría haber cambiado desde entonces. Las reseñas realizadas por otros miembros de la comunidad se marcan con un * en la última columna.

Además, el revisor puede enviar Pull Requests en GitHub cuando encuentra un problema que se puede solucionar. Algunas puden ser aceptadas y fusionadas, y otras simplemente ignoradas.
Así que, si habéis realizado un cambio importante y esperáis que la reseña cambie, simplemente avisad al revisor.

# Package Review Stars IPM Docker *
1 IRIS OpenTelemetry Demo impressive 7 containers concert 5.5   y  
2 DBdashboard impressive catch 5.0   y *
3 DBfree super multi instance monitoring 5.0   y *
4 IRIS-EchoServer-WebSockets echo inside IRIS 5.0   y *
5 iris-health-fhir-agentic-demo not just big but great 5.0   y *
6 ML Made Easy : IntegratedML an excellent training for beginners 5.0   y  
7 restoreUI a pleasure to work with 5.0 y y  
8 WebSocketsSample hidden treasure detected 5.0      
9 CSV-to-MS-OFX rare subject 4.8   y *
10 GeoDatas works partially 3.5   y  
11 CommunityEns requires some adjustments 3.3   y  
12 ALPHA LOGISTICS partner posting *      
13 ERP Plenum partner posting *      

 

NOTA:
Si alguna reseña no os resulta legible, podría estar pendiente de aprobación por los administradores de OEX.

Discussion (0)1
Log in or sign up to continue
Article
· Jan 28 34m read

Sécurité dans IRIS

La sécurité est fondamentale pour le développement d'applications d'entreprise. InterSystems IRIS fournit un cadre de sécurité complet qui protège les données, contrôle l'accès et garantit la conformité. Ce guide présente les fonctionnalités de sécurité essentielles pour les développeurs novices dans IRIS, couvrant l'authentification, l'autorisation, le chiffrement et les stratégies de mise en œuvre pratiques.

Discussion (0)1
Log in or sign up to continue
Discussion
· Jan 28

Proven results Best Urologist in chickpet

The Best Urologist in chickpet, Dr. Anil Kumar T, delivers advanced treatment for urological diseases and tumors using minimally invasive techniques. Patients benefit from reduced recovery time, improved comfort, and structured care plans. His patient-centered consultations, accurate diagnosis, and individualized care ensure effective outcomes. Known for consistent results and ethical practice, he has earned a strong reputation in Chickpet. Individuals seeking reliable and professional urology care trust his expertise, experience, and dedication to patient health.

Discussion (0)1
Log in or sign up to continue