devstory

Analyser JSON dans TypeScript avec la bibliothèque json2typescript

  1. json2typescript
  2. Installation
  3. Exemple de base
  4. @JsonProperty
  5. @JsonConverter

1. json2typescript

json2typescript est une bibliothèque qui contient des classes d'assistance (helper classes) pour définir un mappage entre un document JSON et un objet TypeScript. Cette bibliothèque est inspirée de Java Jackson et possède des fonctionnalités similaires.
En règle générale, json2typescript convient aux grands projets qui nécessitent quelques étapes de configuration. Si vous travaillez uniquement avec JSON dans un petit projet TypeScript, vous pouvez envisager d'utiliser les méthodes JSON.parse(..) et JSON.stringify(..), qui sont accessibles et n'exigent aucune configuration supplémentaire.

2. Installation

Tout d'abord, installer la bibliothèque json2typescript dans le projet :
npm install json2typescript
Ensuite, ajouter les propriétés suivantes au fichier tsconfig.json :
tsconfig.json
{
  "compilerOptions": {  
    ...
    "experimentalDecorators": true,
    "allowJs": true
  }
}

3. Exemple de base

Dans cet exemple, on va créer 2 fichiers model :
  • model_file1.ts
  • model_file2.ts.
Les classes sont définies dans les fichiers modèles. Utiliser @JsonObject et @JsonProperty pour annoter la classe et ses propriétés afin de suggérer à l'outil comment convertir les objets TypeScript en texte JSON et vice versa.
@JsonObject
Une classe est annotée (annotate) avec @JsonObject, puis son objet peut être converti en texte JSON et vice versa.
@JsonProperty
Une propriété d'un objet TypeScript peut être convertie en une propriété de JSON si elle est annotée par @JsonProperty. Sinon, il sera ignoré.
Toutes les propriétés de la classe TypeScript annotées par @JsonProperty doivent être définies sur les valeurs par défaut. Sinon, le résultat peut ne pas être ce que vous attendez.
model_file1.ts
import {
    JsonObject, JsonProperty, JsonConvert, OperationMode,
    ValueCheckingMode, PropertyConvertingMode
} from "json2typescript";

@JsonObject("Contact")
export class Contact {
    // PropertyConvertingMode.MAP_NULLABLE is default.
    // MAP_NULLABLE: Throw Exception if JSON value is undefined
    // IGNORE_NULLABLE: Using Java property default value if JSON value is undefined
    // PASS_NULLABLE: Set Java property value to null if JSON value is undefined
    @JsonProperty("address", String, PropertyConvertingMode.MAP_NULLABLE)
    address: string = '';
    @JsonProperty("phone", String, PropertyConvertingMode.MAP_NULLABLE)
    phone: string = '';
}
@JsonObject("Employee")
export class Employee {
    @JsonProperty("employeeName", String, PropertyConvertingMode.MAP_NULLABLE)
    name: string = '';
    @JsonProperty("email", String, PropertyConvertingMode.MAP_NULLABLE)
    email: string = '';
    @JsonProperty("contact", Contact, PropertyConvertingMode.PASS_NULLABLE)
    contact?: Contact = new Contact();
}
PropertyConvertingMode.MAP_NULLABLE:
Il s'agit du mode de conversion par défaut. Une exception sera lancée s'il n'y a pas de propriété JSON correspondant à cette propriété de la classe TypeScript.
PropertyConvertingMode.IGNORE_NULLABLE:
La propriété de l'objet TypeScript obtiendra la valeur par défaut s'il n'y a pas de propriété correspondante dans JSON.
PropertyConvertingMode.PASS_NULLABLE:
La propriété de l'objet TypeScript sera null s'il n'y a pas de propriété correspondante dans JSON.
model_file2.ts
import {
    JsonObject, JsonProperty, JsonConvert, OperationMode,
    ValueCheckingMode, PropertyConvertingMode
} from "json2typescript";

import { Contact } from './model_file1';

@JsonObject("Company")
class Company {
    @JsonProperty("companyName", String, PropertyConvertingMode.MAP_NULLABLE)
    name: string = '';
    @JsonProperty("contact", Contact, PropertyConvertingMode.PASS_NULLABLE)
    contact?: Contact = new Contact();
}
Si vous utilisez Visual Studio Code pour écrire du code, vous pouvez obtenir un message d'erreur comme ci-dessous. Voyez comment corriger l'erreur partagée sur stackoverflow :
Experimental support for decorators is a feature that is subject to change in a future release. Set the 'experimentalDecorators' option in your 'tsconfig' or 'jsconfig' to remove this warning.ts(1219)
json2typescript_ex1.ts
import {
    JsonObject, JsonConvert, OperationMode, ValueCheckingMode
} from "json2typescript";

import { Employee, Contact } from './model_file1';

// @see Employee class in model_file1.ts
let jsonStr = `  {
    "employeeName": "John Smith",
    "email": "john@example.com",
    "contact": {
       "address": "Address 1",
       "phone": "12345"
    }
} `;
let jsonConvert: JsonConvert = new JsonConvert();

// ----------- JSON Text to TypeScript Object ------------------  
let jsonObj: any = JSON.parse(jsonStr);  
let emp: Employee = jsonConvert.deserializeObject(jsonObj, Employee);
console.log('JSON to TypeScript:');
console.log(emp);
console.log(' ------------- ');

// ----------- TypeScript Object to JSON Text ------------------
let jsonText = jsonConvert.serialize(emp);
console.log('TypeScript to JSON:');
console.log(jsonText);
Output:
JSON to TypeScript:
Employee {
  name: 'John Smith',
  email: 'john@example.com',
  contact: Contact { address: 'Address 1', phone: '12345' }
}
 -------------
TypeScript to JSON:
{
  employeeName: 'John Smith',
  email: 'john@example.com',
  contact: { address: 'Address 1', phone: '12345' }
}
json2typescript_ex2.ts
import {
    JsonObject, JsonConvert, OperationMode, ValueCheckingMode
} from "json2typescript";

import { Employee, Contact } from './model_file1';

// @see Employee class in model_file1.ts
let jsonStr = `  {
   "employeeName": "John Smith",
    "email": "john@example.com"
} `;
let jsonConvert: JsonConvert = new JsonConvert();

// ----------- JSON Text to TypeScript Object ------------------
let jsonObj: any = JSON.parse(jsonStr);  
let emp: Employee = jsonConvert.deserializeObject(jsonObj, Employee);
console.log('JSON to TypeScript:');
console.log(emp);
console.log(' ------------- ');

// ----------- TypeScript Object to JSON Text ------------------
let jsonText = jsonConvert.serialize(emp);
console.log('TypeScript to JSON:');
console.log(jsonText);
Output:
JSON to TypeScript:
Employee {
  name: 'John Smith',
  email: 'john@example.com',
  contact: undefined
}
-------------
TypeScript to JSON:
{
  employeeName: 'John Smith',
  email: 'john@example.com',
  contact: undefined
}

4. @JsonProperty

Une propriété d'un objet TypeScript peut être convertie en une propriété de JSON si elle est annotée par @JsonProperty. Sinon, il sera ignoré.
Toutes les propriétés de la classe TypeScript annotées par @JsonProperty doivent être définies sur les valeurs par défaut. Sinon, le résultat peut ne pas être ce que vous attendez.
Par exemple :
// Model class:
@JsonObject("User")
export class User {
    @JsonProperty("userName", String, PropertyConvertingMode.MAP_NULLABLE)
    userName: string = '';
    @JsonProperty("joinDate", DateConverter)
    joinDate: Date = new Date();
}
La syntaxe :
@JsonProperty("JSON_Property_Name", JSON_Type, Custom_Converter, PropertyConvertingMode)
JSON_Property_Name
Le nom de la propriété en JSON.
JSON_Type (Optional)
Un type de données JSON.
  • String, [String]
  • Number, [Number]
  • Boolean, [Boolean]
  • Any, [Any]
Custom_Converter (Optional)
Voir les exemples dans la section @JsonConverter.
PropertyConvertingMode (Optional)
PropertyConvertingMode.MAP_NULLABLE:
  • Il s'agit du mode de conversion par défaut. Une exception sera lancée s'il n'y a pas de propriété JSON correspondant à cette propriété de la classe TypeScript.
PropertyConvertingMode.IGNORE_NULLABLE:
  • La propriété de l'objet TypeScript obtiendra la valeur par défaut s'il n'y a pas de propriété correspondante dans JSON.
PropertyConvertingMode.PASS_NULLABLE:
  • La propriété de l'objet TypeScript sera null s'il n'y a pas de propriété correspondante dans JSON.

5. @JsonConverter

Dans certains cas, vous devrez peut-être effectuer une conversion personnalisée entre les objets JSON et les objets TypeScript. Vous pouvez définir des convertisseurs personnalisés comme ceci :
model_file3.ts
import {
    JsonObject, JsonProperty, JsonConvert, OperationMode,
    ValueCheckingMode, PropertyConvertingMode, JsonConverter, JsonCustomConvert
} from "json2typescript";
// Custom Converter:
@JsonConverter
class DateConverter implements JsonCustomConvert<Date> {
    serialize(date: Date): any {
        return date.getFullYear() + "-" + (date.getMonth() + 1) + "-" + date.getDate();
    }
    deserialize(date: any): Date {
        return new Date(date);
    }
}
// Model class:
@JsonObject("User")
export class User {
    @JsonProperty("userName", String, PropertyConvertingMode.MAP_NULLABLE)
    userName: string = '';
    @JsonProperty("joinDate", DateConverter)
    joinDate: Date = new Date();
}
json2typescript_ex3.ts
import {
    JsonObject, JsonConvert, OperationMode, ValueCheckingMode
} from "json2typescript";

import { User  } from './model_file3';

// @see User class in model_file3.ts
let jsonStr = `  {
   "userName": "tom",
    "joinDate": "2021-12-15"
} `;
let jsonConvert: JsonConvert = new JsonConvert();

// ----------- JSON Text to TypeScript Object ------------------
let jsonObj: any = JSON.parse(jsonStr);  
let user: User = jsonConvert.deserializeObject(jsonObj, User);
console.log('JSON to TypeScript:');
console.log(user);
console.log(' ------------- ');

// ----------- TypeScript Object to JSON Text ------------------
let jsonText = jsonConvert.serialize(user);
console.log('TypeScript to JSON:');
console.log(jsonText);
Output:
JSON to TypeScript:
User { userName: 'tom', joinDate: 2021-12-15T00:00:00.000Z }
 -------------
TypeScript to JSON:
{ userName: 'tom', joinDate: '2021-12-15' }