Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow serializing enums to integers in JSON output #96

Closed
ToluwaniO opened this issue Jul 1, 2020 · 7 comments
Closed

Allow serializing enums to integers in JSON output #96

ToluwaniO opened this issue Jul 1, 2020 · 7 comments
Labels
enhancement New feature or request

Comments

@ToluwaniO
Copy link

Is it possible to add a build option to serialize enums to integers instead of strings?
Here's what the library currently generates

export const ApprovalState = {
  APPROVED: 0 as const,
  PENDING: 1 as const,
  DENIED: 2 as const,
  UNRECOGNIZED: -1 as const,
  fromJSON(object: any): ApprovalState {
    switch (object) {
      case 0:
      case "APPROVED":
        return ApprovalState.APPROVED;
      case 1:
      case "PENDING":
        return ApprovalState.PENDING;
      case 2:
      case "DENIED":
        return ApprovalState.DENIED;
      case -1:
      case "UNRECOGNIZED":
      default:
        return ApprovalState.UNRECOGNIZED;
    }
  },
  toJSON(object: ApprovalState): string {
    
switch (object) {
      case ApprovalState.APPROVED:
        return "APPROVED";
      case ApprovalState.PENDING:
        return "PENDING";
      case ApprovalState.DENIED:
        return "DENIED";
      default:
        return "UNKNOWN";
    }
  },
}

Here's what I'm trying to achieve

export const ApprovalState = {
  APPROVED: 0 as const,
  PENDING: 1 as const,
  DENIED: 2 as const,
  UNRECOGNIZED: -1 as const,
  fromJSON(object: any): ApprovalState {
    switch (object) {
      case 0:
      case "APPROVED":
        return ApprovalState.APPROVED;
      case 1:
      case "PENDING":
        return ApprovalState.PENDING;
      case 2:
      case "DENIED":
        return ApprovalState.DENIED;
      case -1:
      case "UNRECOGNIZED":
      default:
        return ApprovalState.UNRECOGNIZED;
    }
  },
  toJSON(object: ApprovalState): string {
    
switch (object) {
      case ApprovalState.APPROVED:
        return 0;
      case ApprovalState.PENDING:
        return 1;
      case ApprovalState.DENIED:
        return 2;
      default:
        return -1;
    }
  },
}

My backend is written in Go and has troubling working with data from my ts client because Go uses integers when generating enums.

@stephenh
Copy link
Owner

Hm, I was thinking that protobuf dictated the enums-in-JSON should be strings, but you're right that it says either strings or tags are supported (and we already support parsing either, which I forgot about).

So yeah, I think some sort of something like jsonEnumValues=strings|integers flag seems fine.

Could you submit a PR?

Thanks!

@stephenh stephenh added the enhancement New feature or request label Aug 16, 2020
@stephenh stephenh changed the title option to serialize ts enums to integers instead of string Allow serializing enums to integers in JSON output Aug 16, 2020
@timostamm
Copy link
Contributor

Just chiming in with some points (after implementing canonical JSON in another project):

  • Enum values as integers in JSON should probably a runtime option, not a plugin flag.
  • The recommended options are:
    • Emit enum values as integers instead of strings. <- what this issue is about
    • Emit fields with default values
    • Use proto field name instead of lowerCamelCase name
    • Ignore unknown fields (when reading JSON)
  • reading JSON should accept integer / string for enum <- what this issue is about
  • reading JSON must also accept proto field name
  • field option json_name must be honored in JSON read / write

@stephenh
Copy link
Owner

reading JSON should accept integer / string for enum

We do this already, on reading:

export function stateEnumFromJSON(object: any): StateEnum {
  switch (object) {
    case 0:
    case "UNKNOWN":
      return StateEnum.UNKNOWN;
    case 2:
    case "ON":
      return StateEnum.ON;
    case 3:
    case "OFF":
      return StateEnum.OFF;
    case -1:
    case "UNRECOGNIZED":
    default:
      return StateEnum.UNRECOGNIZED;
  }
}

So I think this issue is about only "Emit enum values as integers instead of strings".

This should actually be a really easy change, assuming it's a build-time config option...

Supporting protobuf field names and json_name is interesting, but would be a separate enhancement and little more involved.

@hijamoya
Copy link

hijamoya commented Mar 9, 2022

Any progress?

@stephenh
Copy link
Owner

stephenh commented Mar 9, 2022

@hijamoya nope, would be great if you're interested in making a PR; the code is around here:

https://github.com/stephenh/ts-proto/blob/main/src%2Fenums.ts#L115

@kev0960
Copy link
Contributor

kev0960 commented Jul 26, 2022

I created a pull request for this.

#625

@stephenh
Copy link
Owner

Fixed in #625, thanks @kev0960 !

zfy0701 pushed a commit to sentioxyz/ts-proto that referenced this issue Jan 5, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

5 participants