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

Feature: Add @encode decorator #1899

Merged
merged 11 commits into from
May 4, 2023

Conversation

timotheeguerin
Copy link
Member

@timotheeguerin timotheeguerin commented May 3, 2023

fix #282

Examples

Specify uuid, email, ipv4, ipv6

model Bar {
  @format("uuid") id: string;
  @format("email") userEmail: string;
  @format("ipv4") ipv4: string;
  @format("ipv6") ipv6: string;
}

Specify base64 or base64url encoding

model Bar {
  @encode("base64") data: bytes;
  @encode("base64url") data2: string;

  // This is how it is currently. So this would have to change
  @format("base64") data: bytes;
  @format("base64url") data2: string;
}

Specify serialization using rfc3339 standard

model Bar {
  @encode("rfc3339")
  createdAt: utcDateTime;

  @encode("rfc3339")
  modifiedAt: offsetDateTime;

  @encode("rfc3339")
  runtime: duration;

  // We could also technically represent the datetime as a string and then we'd use the `@format` decorator to specify the pattern of that string
  @format("date-time")
  createdAtButString: string;
}

Specify serialization using rfc7231 standard

model Bar {
  @encode("rfc7231")
  createdAt: utcDateTime;

  @encode("rfc7231")
  modifiedAt: offsetDateTime;

  @encode("rfc7231")
  runtime: duration;

  @format("date-time-rfc7231")
  createdAtButString: string;
}

Specify serialization using unixTimestamp

model Bar {
  @encode("unixTimestamp", int32)
  createdAt: utcDateTime;

  @encode("unixTimestamp", int32)  // invalid
  modifiedAt: offsetDateTime;

  @encode("unixTimestamp", int32) // invalid
  runtime: duration;


}

Specify Duration serialized as seconds

model Bar {
  @encode("seconds", float64)
  runtimeAsDouble: duration;
  @encode("seconds", int32)
  runtimeAsInt: duration;
}

Formats that move to @encode

Deprecate using @format on bytes

  • base64url
  • base64

Logic for emitter:

  • Generated type: use the actual typespec type
  • Over the wire type:
    • lookup for @encode decorator
      • if absent use typespec type (or default way of serializing that type)
      • if present respect type provided in @encode

@github-actions
Copy link
Contributor

github-actions bot commented May 3, 2023

Changes in this PR will be published to the following url to try(check status of TypeSpec Pull Request Try It pipeline for publish status):
Playground: https://cadlplayground.z22.web.core.windows.net/prs/1899/

Website: https://cadlwebsite.z1.web.core.windows.net/prs/1899/

@MaryGao
Copy link
Member

MaryGao commented May 10, 2023

@timotheeguerin Could you help on the differences for below two statements? Are they equivalent?

// Statement 1
model Bar {
  @encode("rfc7231")
  createdAt: utcDateTime;
}

// Statement 2
model Bar {
  @format("date-time-rfc7231")
  createdAt: string;
}

@timotheeguerin
Copy link
Member Author

Hey @MaryGao they are kind of equivalent for what it means over the wire but they are not equivalent for what you’d expect in the client.

In the encode case you are saying that property is a date time conceptually and so would want to represent that in the client/server code.

in the format case you are saying it is a string conceptually but it happens to be in the pattern of a rfc7231 date time. So in this case the client/server should only represent it as a string.

i would think of format as a know pattern for string and that’s it. You shouldn’t do anything special about but validation(if you are doing validation)

@MaryGao
Copy link
Member

MaryGao commented Sep 11, 2023

@timotheeguerin One more follow-up question, what is the expected string format if a typespec utcDateTime without any encode? "yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'FFFFFFF'Z'" or others ? the same question for offsetDateTime?

model Bar {
  createdAt: utcDateTime;
  endAt: offsetDateTime;
}

@timotheeguerin
Copy link
Member Author

@MaryGao it depends on the protocol and other things, For http there is documentation about all the default encoding of non primitive types here https://microsoft.github.io/typespec/next/standard-library/http/encoding#utcdatetime-and-offsetdatetime

@qiaozha
Copy link
Member

qiaozha commented Sep 12, 2023

@timotheeguerin I might miss something, in the offsetDateTime description, it gives an example of "April 10th at 3:00am in PST" which should be rfc7231 by default as I understand it.

https://github.com/microsoft/typespec/blob/main/packages/compiler/lib/lib.tsp#L108-L111

but in the documentation, it says the default format for offsetDateTime is something like "2022-10-25T07:20:50.52+07:00" which by the way is also not the standard rfc3339 format if I understand correctly ?

@timotheeguerin
Copy link
Member Author

timotheeguerin commented Sep 12, 2023

In the first doc you linked it just shows the concept of a zoned date time that string is not rfc7231 either.

@bterlson
Copy link
Member

It is rfc7231 only when used as a header, otherwise rfc3339. Can you point out the part of the example that is invalid?

@qiaozha
Copy link
Member

qiaozha commented Sep 12, 2023

"+07:00" inside "2022-10-25T07:20:50.52+07:00" ?

@timotheeguerin
Copy link
Member Author

It is no? https://ijmacd.github.io/rfc3339-iso8601/
How else do you expect the offset to be specified?

@bterlson
Copy link
Member

You can see the offset syntax in the grammar here also: https://datatracker.ietf.org/doc/html/rfc3339#section-5.6

@qiaozha
Copy link
Member

qiaozha commented Sep 12, 2023

Got it, Thank you all for the pointers.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Implement decorator to support date serialization format
5 participants