json2typescript icon indicating copy to clipboard operation
json2typescript copied to clipboard

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

Open nicolaedaian opened this issue 6 years ago • 3 comments
trafficstars

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);

nicolaedaian avatar Jun 24 '19 21:06 nicolaedaian

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!

andreas-aeschlimann avatar Jun 26 '19 18:06 andreas-aeschlimann

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

nicolaedaian avatar Jun 26 '19 22:06 nicolaedaian

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.

andreas-aeschlimann avatar Jun 27 '19 12:06 andreas-aeschlimann