appvision-gmbh / json2typescript

Map JSON to a TypeScript class with secure type checking!
https://www.npmjs.com/package/json2typescript
MIT License
278 stars 55 forks source link

How to serialize the name of the property instead of the name of the base class field? #107

Open nicolaedaian opened 5 years ago

nicolaedaian commented 5 years ago

Please look at the below code. I expect the result of the serialization to be

{
    "origin": {
        "x": 1,
        "y": 2
    },
    "size": {
        "width": 3,
        "height": 4
    }
}

Instead it is

{
    "origin": {
        "a": 1,
        "b": 2
    },
    "size": {
        "a": 3,
        "b": 4
    }
}

How can I make json2typescript to use the name of the properties in the Coord and Size classes instead of using the name of the properties in the (common) base class Pair?

@JsonObject("Pair")
export class Pair2
{
    @JsonProperty("a", Number)
    protected a: number;
    @JsonProperty("b", Number)
    protected b: number;

    constructor(a?: number, b?: number)
    {
        this.a = a;
        this.b = b;
    }
}

@JsonObject("Coord")
export class Coord2 extends Pair2
{
    @JsonProperty("x", Number)
    public get x(): number { return this.a; }
    public set x(value: number) { this.a = value; }

    @JsonProperty("y", Number)
    public get y(): number { return this.b };
    public set y(value: number) { this.b = value };

    constructor(x?: number, y?: number)
    {
        super(x, y);
    }
}

@JsonObject("Size")
export class Size2 extends Pair2
{
    @JsonProperty("width", Number)
    public get width(): number { return this.a; }
    public set width(value: number) { this.a = value; }

    @JsonProperty("height", Number)
    public get height(): number { return this.b };
    public set height(value: number) { this.b = value };

    constructor(width?: number, height?: number)
    {
        super(width, height);
    }
}

@JsonObject("Rectangle")
export class Rectangle2
{
    @JsonProperty("origin", Coord2)
    origin: Coord2;
    @JsonProperty("size", Size2)
    size: Size2;

    constructor(origin: Coord2, size: Size2)
    {
        this.origin = origin;
        this.size = size;
    }
}

let jsonConvert: JsonConvert = new JsonConvert();
jsonConvert.operationMode = OperationMode.LOGGING; // print some debug data
jsonConvert.ignorePrimitiveChecks = false; // don't allow assigning number to string etc.
jsonConvert.valueCheckingMode = ValueCheckingMode.DISALLOW_NULL; // never allow null

let origin = new Coord2(1, 2);
let size = new Size2(3, 4);
let rectangle = new Rectangle2(origin, size);

let rectangleJsonObj = jsonConvert.serialize(rectangle);
console.log(rectangleJsonObj);
let rectangleStr = JSON.stringify(rectangleJsonObj);
console.log(rectangleStr);
andreas-aeschlimann commented 5 years ago

I don't think json2typescript will properly work with get/set methods for properties, you should always use it with the field.

I don't know if it would be easy to implement this, but I don't think so. If you know, you are welcome to give some input!

nicolaedaian commented 5 years ago

Yeah, I ended up doing the following:

  1. Instead of using the json2typescript library I used JSON.stringify and JSON.parse
  2. I used toJSON() to return an object that has width and height as below:
private toJSON = () =>
{
    return {
        width: this.width,
        height: this.height
    }
}
andreas-aeschlimann commented 5 years ago

You could also use custom converters and call the set/get methods there. But the decorator needs to be set to the field.

Custom converters are a good way to assign anything you want, not just simple strings. We could actually implement a solution where json2typescript automatically calls the get/set methods, if there are some. I will keep this open for future reference.