{"id":22530156,"url":"https://github.com/ultimaweapon/json-mapper","last_synced_at":"2025-08-03T23:33:39.236Z","repository":{"id":46300673,"uuid":"394551484","full_name":"ultimaweapon/json-mapper","owner":"ultimaweapon","description":"Make your JSON type-safe with TypeScript decorators","archived":false,"fork":false,"pushed_at":"2022-02-14T01:01:53.000Z","size":29,"stargazers_count":6,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2024-11-10T23:56:03.007Z","etag":null,"topics":["json","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ultimaweapon.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-08-10T06:40:57.000Z","updated_at":"2024-08-06T08:11:09.000Z","dependencies_parsed_at":"2022-09-19T09:12:00.950Z","dependency_job_id":null,"html_url":"https://github.com/ultimaweapon/json-mapper","commit_stats":null,"previous_names":["ultimicro/json-mapper"],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ultimaweapon%2Fjson-mapper","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ultimaweapon%2Fjson-mapper/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ultimaweapon%2Fjson-mapper/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ultimaweapon%2Fjson-mapper/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ultimaweapon","download_url":"https://codeload.github.com/ultimaweapon/json-mapper/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":228572364,"owners_count":17938874,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["json","typescript"],"created_at":"2024-12-07T07:18:31.078Z","updated_at":"2024-12-07T07:18:31.792Z","avatar_url":"https://github.com/ultimaweapon.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# TypeScript decorators for mapping between JSON and Classes\n[![npm (scoped)](https://img.shields.io/npm/v/@ultimicro/json-mapper)](https://www.npmjs.com/package/@ultimicro/json-mapper)\n\nThis is a powerful utility to convert and validate JSON value for TypeScript. The main purposes of this library is to enforce JSON schemas and make it\nable to use `instanceof` to determine the type of JSON value.\n\nThe original source code of this package came from https://github.com/GillianPerard/typescript-json-serializer\n\n## Runtime requirements\n\n- ES2015\n- [reflect-metadata](https://www.npmjs.com/package/reflect-metadata)\n\n## Required compiler options\n\n- `experimentalDecorators`\n- `emitDecoratorMetadata`\n\n## Basic usages\n\n### Create model\n\nCreate a model to represent a JSON object:\n\n```ts\nimport { JsonClass, JsonProperty } from '@ultimicro/json-mapper';\n\n@JsonClass()\nclass Foo {\n  @JsonProperty()\n  v1: string;\n\n  @JsonProperty({ type: Number }) // nullable type required to specify type explicitly\n  v2: number | null;\n\n  @JsonProperty({ args: [String] })\n  v3: string[];\n\n  @JsonProperty({ args: [Date] })\n  v4: Map\u003cstring, Date\u003e;\n\n  @JsonProperty({ optional: true })\n  v5?: Date;\n\n  constructor(v1: string, v2: number | null, v3: string[], v4: Map\u003cstring, Date\u003e) {\n    this.v1 = v1;\n    this.v2 = v2;\n    this.v3 = v3;\n    this.v4 = v4;\n  }\n}\n```\n\n### Convert JSON to the model instance\n\n```ts\nimport { fromJSON } from '@ultimicro/json-mapper';\n\nconst json = JSON.parse('{\"v1\": \"abc\", \"v2\": 123, \"v3\": [\"foo\"], \"v4\": \"2006-01-02T15:04:05.000Z\"}');\nconst model = fromJSON(json, Foo);\n```\n\n### Convert the model instance to JSON\n\n```ts\nimport { toJSON } from '@ultimicro/json-mapper';\n\nconst model = new Foo('abc', 123, ['foo']);\nconst str = toJSON(model);\nconst obj = toJSON(model, false); // invoke JSON.stringify(obj) to get JSON string\n```\n\n## Advanced usage\n\n### Map a class as single value instead of object\n\n```ts\nimport { InvalidProperty, JsonArray, JsonClass, JsonObject, JsonScalar, MappingContext } from '@ultimicro/json-mapper';\n\n@JsonClass({ reader: readBar, writer: writeBar })\nclass Bar {\n  constructor(readonly value: string) {\n  }\n}\n\nfunction readBar(ctx: MappingContext, json: JsonScalar | JsonObject | JsonArray): Bar {\n  if (typeof json !== 'string') {\n    throw new InvalidProperty(`Expect string, got ${typeof json}.`, ctx.currentPath());\n  }\n\n  return new Bar(json);\n}\n\nfunction writeBar(ctx: MappingContext, obj: Bar): JsonScalar | JsonObject | JsonArray {\n  return obj.value;\n}\n```\n\n### Using 3rd party classes as a model\n\n```ts\nimport { configClass, configProperty } from '@ultimicro/json-mapper';\nimport { SomeClass } from 'somelib';\n\n// the bottom code MUST run exactly one\nconfigClass(SomeClass); // use the second argument to specify custom reader/writer to treat this class as a single value like the above example\nconfigProperty(SomeClass, { name: 'prop1', type: String }); // you can use any additional options that are available on JsonProperty\n\n// now you can use SomeClass as a JSON model anywhere\n```\n\n### Property with dynamic type\n\n```ts\nimport { InvalidProperty, JsonClass, JsonProperty, JsonValue, MappingContext, Type } from '@ultimicro/json-mapper';\n\n@JsonClass()\nclass Foo {\n  @JsonProperty({ discriminator: getValueType })\n  v1: string | number | null;\n\n  constructor(v1: string | number | null) {\n    this.v1 = v1;\n  }\n}\n\nfunction getValueType(ctx: MappingContext, obj: Foo, json: JsonValue): Type | { type: Type, required?: boolean } {\n  if (json === null) {\n    return null;\n  }\n\n  // you can access all PREVIOUS properties of your class here\n  switch (typeof json) {\n    case 'string':\n      return String;\n    case 'number':\n      return Number;\n    default:\n      throw new InvalidProperty(`Unknown value ${typeof json}.`, ctx.currentPath());\n  }\n}\n```\n\n### Polymorphism support\n\nPolymorphism work by constructing a base object then invoke `getType` after mapping is completed to get a constructor of the real value, which will\nget invoked afterward and map all remaining properties. Then the properties of the base object will be moved to the real value except if it is marked\nwith `movable: false`:\n\n```ts\nimport { Constructor, GenericClass, InvalidProperty, JsonClass, JsonProperty, MappingContext, PolymorphismObject } from '@ultimicro/json-mapper';\n\nconst enum ValueType {\n  Foo = 0,\n  Bar = 1\n}\n\n@JsonClass()\nabstract class Base implements PolymorphismObject {\n  constructor(type: ValueType) {\n    this.type = type;\n  }\n\n  getType(ctx: MappingContext): Constructor | GenericClass {\n    switch (this.type) {\n      case ValueType.Foo:\n        return Foo;\n      case ValueType.Bar:\n        return Bar;\n      default:\n        throw new InvalidProperty(`Unknown type ${this.type}.`, ctx.pathFor('type'));\n    }\n  }\n\n  @JsonProperty({ movable: false }) // we don't need to move this value due to the derived class explicitly assign it via constructor\n  private type: ValueType;\n}\n\n@JsonClass()\nclass Foo extends Base {\n  @JsonProperty()\n  v1: string;\n\n  constructor(v1: string) {\n    super(ValueType.Foo);\n    this.v1 = v1;\n  }\n}\n\n@JsonClass()\nclass Bar extends Base {\n  @JsonProperty()\n  v1: number;\n\n  constructor(v1: number) {\n    super(ValueType.Bar);\n    this.v1 = v1;\n  }\n}\n```\n\n### Generic class support\n\n```ts\nimport { JsonClass, JsonProperty } from '@ultimicro/json-mapper';\n\n@JsonClass()\nclass Foo\u003cT1, T2\u003e {\n  @JsonProperty({ type: 0 })\n  v1: T1;\n\n  @JsonProperty({ type: 1, required: false })\n  v2: T2 | null;\n\n  constructor(v1: T1, v2: T2 | null) {\n    this.v1 = v1;\n    this.v2 = v2;\n  }\n}\n\n@JsonClass()\nclass Bar {\n  @JsonProperty({ args: [String, Number] })\n  v1: Foo\u003cstring, number\u003e;\n\n  @JsonProperty({ args: [{ type: String, required: false }, Number] })\n  v2: Foo\u003cstring | null, number\u003e;\n\n  constructor(v1: Foo\u003cstring, number\u003e, v2: Foo\u003cstring | null, number\u003e) {\n    this.v1 = v1;\n    this.v2 = v2;\n  }\n}\n```\n\n## Development\n\n### Running unit tests\n\n```sh\nnpm test\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fultimaweapon%2Fjson-mapper","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fultimaweapon%2Fjson-mapper","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fultimaweapon%2Fjson-mapper/lists"}