typestack / class-transformer

Decorator-based transformation, serialization, and deserialization between objects and classes.
MIT License
6.64k stars 486 forks source link

question: Casting Json to the required datatype #1682

Closed AhmedK-Fawry closed 1 month ago

AhmedK-Fawry commented 4 months ago

I attempted to convert a JSON object to a Restaurant class using the class-transformer library in TypeScript. Below is the code snippet:

import { plainToClass, classToPlain } from 'class-transformer';

export class Restaurant {
  accountNumber?: string;
  monthlyVolume?: number;
  printingTicketEnabled?: string;
  royalPartner?: boolean;
}

export class Convert {
  public static toRestaurant(json: string): Restaurant[] {
    const objectArray: object[] = JSON.parse(json);
    const result: Restaurant[] = objectArray.map((entity) =>
      plainToClass(Restaurant, entity)
    );
    return result;
  }

  public static restaurantToJson(value: Restaurant[]): string {
    const plainObjects = value.map((entity) => classToPlain(entity));
    return JSON.stringify(plainObjects);
  }
}

However, I encountered an issue with the API sending JSON data with varying data types, such as printingTicketEnabled being either a string or a boolean.

I'm seeking a solution to enforce a specific data type (string in this case) for certain properties in the class. If the API sends a different data type, I want to attempt casting it to the specified type instead of excluding it.

I came across { excludeExtraneousValues: true }, but it excludes values. I'm looking for a way to cast the value to the specified data type instead of excluding it. How can I achieve this modification in the code?

diffy0712 commented 4 months ago

Hi Ahmed,

This answer is a bit late, but hopefully it can be helpful!

You can use @Type(() => String) decorator to force type conversion to String in your case!

Your class would look like this:

export class Restaurant {
  @Type(() => String)
  accountNumber?: string;
  @Type(() => Number)
  monthlyVolume?: number;
  @Type(() => String)
  printingTicketEnabled?: string;
  @Type(() => Boolean)
  royalPartner?: boolean;
}

If you need a custom transformer you can read more here

Note: The plainToClass and classToPlain are marked as deprecated. You should use plainToInstance and instanceToPlain respectively. Note2: The plainToInstace and instanceToPlain functions work with array as well! So you don't need the Array.map.

diffy0712 commented 1 month ago

Closing as answered. If you have any questions left feel free to comment on this issue.

github-actions[bot] commented 4 weeks ago

This issue has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs.