I want to establish the identical response output field name in NestJS by utilizing the @Expose decorator from class-transformer

My Entity definition currently looks like this:

export class ItemEntity implements Item {

  @PrimaryColumn()
  @IsIn(['product', 'productVariant', 'category'])
  @IsNotEmpty()
  itemType: string;

  @PrimaryColumn()
  @IsUUID()
  @IsNotEmpty()
  itemId: string;

  @OneToOne(() => ProductEntity, product => product.id, { nullable: true })
  @JoinColumn()
  @Expose({ name: 'bundleItem' })
  producttItem: ProductEntity;

  @OneToOne(() => ProductVariantEntity, variant => variant.id, {
    nullable: true,
  })
  @JoinColumn()
  @Expose({ name: 'bundleItem' })
  variantItem: ProductVariantEntity;

  @OneToOne(() => CategoryEntity, category => category.id, { nullable: true })
  @JoinColumn()
  @Expose({ name: 'bundleItem' })
  categoryItem: CategoryEntity;
}

My use of the @Expose() decorator is to ensure that only one of productItem, variantItem, or categoryItem is returned as a single bundleItem field in the response. Only one of them should have a value, not two or three.

However, upon performing a GET request on the ItemEntity's controller, the desired effect is applied only to the first item, not the rest:

[
    {
        "itemType": "category",
        "itemId": ""
        "bundleItem": {
            "categoryType": "Custom",
            "description": "First custom category",
            "id": "e00ad76c-95d3-4215-84b1-de17c7f1f82c",
            "name": "Category A",
            "updatedAt": "2023-02-24T08:49:22.913Z"
        }
    },
    {
        "itemType": "variant",
        "itemId": "",
        "bundletem": null
    }
]

I aim to extend this effect to all items in the response array. Currently, the other items are returning as null. In essence, I want the response to include a bundleItem field regardless of the itemType (be it productItem, variantItem, or categoryItem). Is it possible to achieve this using `class-transformer`?

Thank you.

Answer №1

If you're looking to streamline your transformation process, consider utilizing the @Transform decorator. This decorator offers various arguments that can be leveraged during the transform operation, including access to the object itself.

@Transform(({ value, key, obj, type }) => value)

For instance, in the code snippet below, we have an object with two properties. If one of these properties is either null or undefined, the other property is returned instead.

import {Exclude, Expose, Transform} from "class-transformer";

export class ExampleDto {
  constructor(partial: Partial<ExampleDto>) {
    Object.assign(this, partial);
  }

  @Expose()
  name: string;

  @Expose({ name: "new_property" })
  @Transform(({ value, key, obj, type }) => {
    return obj.property1 ?? obj.property2;
  })
  property1: string | null;

  @Exclude()
  property2: string | null;
}

Within the Controller:

  @Get("example")
  @UseInterceptors(ClassSerializerInterceptor)
  getExample(): ExampleDto {
    return new ExampleDto({
      name: "Name",
      property2: "value 2"
    });
  }

The output will be:

{
    "name": "Name",
    "new_property": "value 2"
}

While this approach may be effective, it is strongly advised to separate your database entity from the DTOs. Using the same class for both purposes can lead to potential issues, as the entity serves as a representation in the database and a contract with the external world simultaneously. Any modifications to your model will impact the API and vice versa.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Angular 9's Jasmine Mocking Provider Featuring Unique Methods and Properties

Currently, I am attempting to mimic the functionality of the angularx-social-login npm package. My goal is for the default test to be created and passed successfully. In my test specification, the following code is included: let component: Component; l ...

Errors with the email composer in Ionic 3 displaying "plugin_not_installed" issue

Currently utilizing this feature within my Ionic 3 application. The plugin has been successfully installed, and the cordova-plugin-email-composer folder is present in the plugins directory. Despite multiple attempts of uninstalling and reinstalling, an err ...

Uploading CSV files in Angular 4

I am currently working on an Angular4 project where I have implemented a feature that converts data into a CSV file with a header. Now, I am looking to reverse this process and allow users to upload a CSV file instead. To test this functionality, I create ...

Uploading files using Ajax in the Laravel framework

I am attempting to utilize ajax to upload a file in Laravel. $("#stepbutton2").click(function(){ var uploadFile = document.getElementById("largeImage"); if( ""==uploadFile.value){ } else{ v ...

Ways to prevent the Layout component from rendering on the NextJS login page

Is there a way to prevent the rendering of the Layout component in NextJS when the route is /login, /register, etc? const MyApp = ({ Component, pageProps }) => { return ( <Layout> <Component {...pageProps} /> </Layout> ...

Does an invisible property value exist?

Instead of: if ( ! $('#XX').is(':visible) ) Is there a property named invisible? I tested that one out, but it seems to not work. Appreciate the help! ...

What could be the reason for the malfunctioning of the header() function in PHP

Currently, I'm utilizing AJAX to facilitate user registration for a service. Here's the code snippet for the submit button: <input type="button" id="register" name="register" class="btn btn-success" onclick="registration();" value="Register"/ ...

The "loose" mode is not resolving the issue with the lack of support for the experimental syntax 'classProperties' that is currently disabled

Error Message: The experimental syntax 'classProperties' is currently not enabled Even after trying the suggested solutions, I still encounter the error during re-building. Click here for more information on the experimental syntax 'classP ...

Having trouble looping through an array in Angular 2?

I am currently using a FirebaseObjectObservable to retrieve the value of a property from my firebase database. The property can have multiple values, so I stored them in a local array variable. However, I ran into an issue while trying to iterate through ...

Fastblox - utilizing javascript SDK for group chatting

I've been facing issues setting up a group chat using QB Javascript SDK. There are a few problems I am encountering: Firstly, I consistently receive a "room is locked" message. Here's the link to the screenshot: https://i.sstatic.net/auR21.png. ...

Is it possible to submit two forms simultaneously using jQuery or AJAX?

My plan is to save 2 forms, with the first form providing the Foreign key for the second form. This is my attempt at saving this using JavaScript: $("#btnSave").click(function (e) { e.preventDefault(); $('#workForm').submit(); ...

What exactly is the purpose of the QueryString function and how does it work

I recently took on the role of editor for a website that I did not create. One of the webpages contains a map feature, and I've been tasked with changing how the map loads initially on the webpage. As I review the JavaScript code, I'm unsure if ...

Using JQuery to locate and substitute occurrences of HTML elements throughout my webpage

Looking for assistance with a JQuery search and replace task involving multiple instances of HTML within a specific DIV element on my webpage. Specifically, I need to change certain items in the textbox to a simpler display format. Here is a snippet of th ...

Navigational menu header leads to specific location on the page

I need the dropdown menu header to both open the related menu and display the content of the first element of the submenu, which is an anchor link on the page. Here is the HTML code for the Dropdown Menu: <div class="collapse navbar-collapse" id="myNa ...

Unraveling the Power of Recursive Functions within a React.JS

I'm encountering an issue with a React project. It involves a tic tac toe game where I'm currently working on the implementation of the computer player. The problem arises when the human player clicks on one square (Field-component), triggering ...

Unexpected Errors Occurring on CRM 2016 Forms

Ever since our upgrade from CRM 2011 to CRM 2016, we've been encountering random script error messages during form loading. Despite properly including all dependency scripts in the form properties, we haven't been able to resolve the issue. I cam ...

How can I retrieve the name of a constant enum member in TypeScript as a string?

Consider the following const enum declaration: const enum Snack { Apple = 0, Banana = 1, Orange = 2, Other = 3 } Is it possible in TypeScript to retrieve the string representation of a specific member? In C#, this could be achieved with ...

Callback function not being triggered in Jquery's getJson method

I am currently faced with a javascript conundrum. Below is the snippet of code that I have been working on: $.get("categories/json_get_cities/" + stateId, function(result) { //code here }, 'json' ); ...

What are the repercussions of labeling a function, TypeScript interface, or TypeScript type with export but never actually importing it? Is this considered poor practice or is there a potential consequence?

I find myself grappling with a seemingly straightforward question that surprisingly has not been asked before by others. I am currently immersed in a TypeScript project involving Vue, and one of the developers has taken to labeling numerous interfaces and ...

The sonar scanner encountered an error while attempting to parse a file using the espree parser in module mode

While executing sonar-scanner on a node project, I encounter a Failed to parse file issue, as shown below: ERROR: Failed to parse file [file:///home/node-app/somedir/index.js] at line 1: Unexpected token './AddCat' (with espree parser in mod ...