Typescript - flat a JSON model using Class-transformer

Viewed 3392

I am trying to use the class transformer in typescript (node.js): https://github.com/typestack/class-transformer

I would like to flat a JSON using only 1 model , 1 Dto that will go to the DB

if I have the following json :

{
 "data":{"test":"123"}
 "name":"x"
}

the DB service should receive the following object:

 {
   "test":"123",
   "name":"x"
 }

This what I tried to define but it's not working :

@Expose()
export class Dto{
  name:string,
  @Expose({name: "data.test"})
  test: string
}

the result on the test field is undefined how can I achieve that? I don't want to create a "mediator" model

3 Answers

according to doc make

@Expose()
@Transform(({obj}) => obj.data.test)
test: string;

you are trying to flatten a JSON object right? I think you should do it manually. like this

function Flatten(myObj){
    const keys = Object.keys(myObj);
    const newObj = {};
    keys.forEach((key)=>{
        if (typeof myObj[key] != "object"){
            newObj[key] = myObj[key];
        }else{
            const nestedObj = Flatten(myObj[key]);
            Object.assign(newObj,nestedObj);
        }
    });
    return newObj;
}

NOTES:
This is not a TypeScript function but you can turn it into one.
This might not work if the nested Object is an array. you have to do extra checks.

Edit:- if the nested object is array change the if Condition to this

   if (typeof myObj[key] == "object" && !Array.isArray(myObj[key])){
        const nestedObj = Flatten(myObj[key]);
        Object.assign(newObj,nestedObj);
    }else{
       
        newObj[key] = myObj[key];
    }

Alternatively, you can do it with both Expose and Transform if data.test is the only property to be flattened.

@Expose({ name: 'data', toClassOnly: true })
@Transform((val) => val.test; }, { toClassOnly: true })
test: string;

If not

@Expose({ toClassOnly: true })
@Transform((val) => val.data.test; }, { toClassOnly: true })
test: string;

@Expose({ toClassOnly: true })
@Transform((val) => val.data.anothertest; }, { toClassOnly: true })
anothertest: string;

Related