routing-controllers icon indicating copy to clipboard operation
routing-controllers copied to clipboard

fix: Enum in @QueryParams and @QueryParam: Value cannot be parsed into JSON

Open DimaIT opened this issue 5 years ago • 16 comments

Some code to reproduce issue:

enum LabelType {
  Sent = 'Sent',
  Inbox = 'Inbox'
}

class Query {
  @IsEnum(LabelType)
  label: LabelType;
}

@JsonController()
export class ThreadController {
  @Get('/threads')
  async list(
    @QueryParams() query: Query
  ) {
    return "ok";
  }
  @Get('/threads/one')
  async list(
    @QueryParam('label') label: LabelType,
  ) {
    return "ok";
  }

  @Post('/threads')
  async postList(
    @Body() query: Query
  ) {
    return "ok";
  }
}

Issue:

Post method is working as expected, but Get fails with this error: Http error: Given parameter label is invalid. Value ("Sent") cannot be parsed into JSON.

Possible reason:

Typescript emits "Object" for "design:type" when type is inferred original issue. In that case string enum treats as an object and routing-controllers tries to parse string. That happens in normalizeParamValue method of ActionParameterHandler here. normalizeParamValue isn't handles params from @Body, that's why Post works as expected.

Workaround:

Until it fixed we can explicitly specify enum type. Not sure if that will not break anything else, but working fine for me:

export class Query {
  @Reflect.metadata('design:type', { name: 'string' })
  @IsEnum(LabelType)
  label: LabelType;
}

For @QueryParam it's possible to set parameter's type:

@QueryParam('label', { type: 'string' }) label: LabelType

DimaIT avatar Dec 23 '19 20:12 DimaIT

Unable to reproduce issue with @QueryParams on test project with no extra dependencies, but still reproducable in work project. For @QueryParam reproducing everywhere, tried routing-controllers 0.7.7 and 0.8.0 typescript 3.7.2 and 3.7.4

Test repo: https://github.com/DimaIT/routing-controllers-enum-issue

DimaIT avatar Dec 24 '19 13:12 DimaIT

Issue is reproducable only with --transpile-only flag for ts-node. Works as expected without it or with compiled files.

DimaIT avatar Jan 14 '20 18:01 DimaIT

Im getting a the same error with union types (string | string[]) or type any. I must pass double quotes (?search="foo") for a single param to work. Im using [email protected], [email protected] [email protected] Here is an example repo

AntonisFK avatar Mar 24 '20 04:03 AntonisFK

I confirm the bug exists on "routing-controllers": "^0.9.0-alpha.2",

Possible workaround:

  @Get('/:id')
  public async get(
    @CurrentUser() currentUser: User,
    @Req() req: any,
    // @Param('id') id: number | string,
  ) {
    // console.log(req);
    const id = req.params.id;
    const item = await this.localManager.findByUserAndReferenceId(currentUser, id);

    return item.getBody();
  }

ivanproskuryakov avatar Aug 20 '20 15:08 ivanproskuryakov

same problem

gtbl2012 avatar May 14 '21 06:05 gtbl2012

same problem here!

exejutable avatar May 31 '21 20:05 exejutable

@gtbl2012 @exejutable been working on similar https://github.com/typestack/routing-controllers/issues/703 and have PR waiting to be merged https://github.com/typestack/routing-controllers/issues/703 Once it will be merged, it would be great if you could test the changes made on your side.

ivanproskuryakov avatar Jun 01 '21 08:06 ivanproskuryakov

same problem version "0.9.0"

Markiz9999 avatar Oct 25 '21 16:10 Markiz9999

same problem here image image image only when covering param with double-quotes, it would be parsed and work. i think it could be a parser problem

Insik-Won avatar Jun 08 '22 15:06 Insik-Won

same problem I cant send something like comment/b481d670 from the front, unless wrap it with double quotes: comment/"b481d670"

miladr0 avatar Jun 20 '22 15:06 miladr0

I had the same error : Http error: Given parameter label is invalid. Value ("state") cannot be parsed into JSON. I upgrade typescript version and that fixed the issue. old version : "typescript": "^4.5.5", new version "typescript": "4.9.5"

i tried with 4.6.2 and it works too.

nicolasPelvet avatar Feb 20 '23 16:02 nicolasPelvet

Updating my TypeScript did not work.

When I build the app and run the JS application, it doesn't show any error =/ Running ts-node without transpile-only worked for me.

Also, I am using type, not enums.

pauloendoh avatar Apr 29 '23 23:04 pauloendoh

@pauloendoh keep it mind types are not available during runtime!

attilaorosz avatar Apr 30 '23 05:04 attilaorosz

@attilaorosz

Yeah, I use the IsIn decorator that accepts an array of values


const itemTypes = ['tvSeries', 'movie'] as const
type ItemType = typeof itemTypes[number]

class Item {
  @IsIn(itemTypes)
  type: ItemType
}

pauloendoh avatar Apr 30 '23 06:04 pauloendoh

Anyone still having this issue? I'm trying with @IsIn as well and it still does not work.

biknandy avatar May 05 '23 04:05 biknandy

I still have this problem, any solutions?

Solang99 avatar Oct 16 '23 08:10 Solang99