Reputation: 49
I am doing custom serialization in TypeScript as shown in example below.
I am serializing all strings as custom types. With the following approach, all the strings are getting replaced fine, but those that are in arrays are getting returned as objects. The expectation is that arrays should stay as arrays in returned new object and it should work fine for the strings that exist in both objects and arrays.
As extra info, I am serializing a custom type other than strings in my project, this is an example of what I am trying to do.
Any inputs?
interface Test {
a: number;
b: Array<string>
}
interface Sample {
x: number;
y: string;
z: Array<Test>;
}
let sample: Sample = {
x: 1,
y: 'hello',
z: [{ a: 10, b: ['hello', 'hi'] }]
};
function isObject(obj: any): boolean {
return obj !== null && typeof obj === 'object';
}
function isString(obj: any): boolean {
return obj !== null && typeof obj === 'string';
}
console.log(`${JSON.stringify(sample)}`);
function customSerializeRecursive(obj: any): any {
const customTypePlaceHolder = {};
for (const entry of Object.entries(obj)) {
const [key, value] = entry;
if (isString(value)) {
customTypePlaceHolder[key] = {
_type: 'test',
_value: value.toString()
};
} else if (isObject(value)) {
customTypePlaceHolder[key] = customSerializeRecursive(value);
}
}
const newObj = { ...obj, ...customTypePlaceHolder };
if (Object.keys(customTypePlaceHolder).length === 0) {
return obj;
} else {
return newObj;
}
}
const newSample = customSerializeRecursive(sample);
console.log(`${JSON.stringify(newSample)}`);
{
"x": 1,
"y": "hello",
"z": [{"a": 10, "b": ["hello", "hi"]}]
}
{
"x": 1,
"y": {"_type": "test", "_value": "hello"},
"z":{"0": {"a": 10, "b": {"0": {"_type": "test", "_value": "hello"}, "1": {"_type": "test", "_value": "hi"}}}}
}
json
shows the passed in object.json
shows the returned object: we can see z
getting converted to an object.Expected Output
{
"x": 1,
"y": "hello",
"z": [{"a": 10, "b": ["hello", "hi"]}]
}
{
"x": 1,
"y": {"_type": "test", "_value": "hello"},
"z": [{"a": 10, "b": [{"_type": "test", "_value": "hello"}, {"_type": "test", "_value": "hi"}]}]
}
Upvotes: 2
Views: 498
Reputation: 3663
A direct answer to your questing will be like this:
const sample: Record<string, any> = {
x: 1,
y: 'hello',
z: [{ a: 10, b: ['hello', 'hi'] }]
};
function replacer(key, value) {
if (['_type', '_value'].includes(key)) {
return value;
}
if (typeof value === 'string') {
return {
_type: 'test',
_value: value,
};
}
return value;
}
console.log(JSON.stringify(sample, replacer, 2));
which will give you the following result:
{
"x": 1,
"y": {
"_type": "test",
"_value": "hello"
},
"z": [
{
"a": 10,
"b": [
{
"_type": "test",
"_value": "hello"
},
{
"_type": "test",
"_value": "hi"
}
]
}
]
}
But my gut tells me that you are trying to invent the wheel, so I would recommend you to check out class-transformer which will help you manipulate plain objects to class and back.
P.S. If you are using typescript try to not use any
.
Upvotes: 1