1

Having a Cloud Endpoints (ProtoRPC) message class with an integer field, e.g.

TestMsg(messages.Message):
  int_field = messages.IntegerField(1)

and a method:

@endpoints.method(VoidMessage, TestMsg)
def test_int_field():
  return TestMsg(int_field=1234567890123)

On local dev server JSON response correctly results in:

{ int_field: 1234567890123 }

Whereas in production the number gets converted to a string for some reason:

{ int_field: "1234567890123" }

For smaller numbers integers don't seem to be converted to strings though.

Is this expected behaviour? Anyone can repro? (In case it matters: I'm running this code in EU datacenters)

alex
  • 2,450
  • 16
  • 22
  • 1
    IIRC endpoints do this when the number is larger than MAX_INT – proppy Apr 13 '13 at 16:15
  • Also see http://stackoverflow.com/questions/8663298/json-transfer-of-bigint-12000000000002539-is-converted-to-12000000000002540 – proppy Apr 13 '13 at 16:22
  • Ah, that would certainly expain it (the MAX_INT thing). Though I did try with Variant.UINT64 and other variants, same result. The other SO question about Javascript converting bigints is another story, I didn't get that far with numbers :) Thanks @proppy – alex Apr 13 '13 at 16:23
  • Problem is, it seems to be somewhere in Endpoints (ProtoRPC doesn't do it). I created an issue, just in case: https://code.google.com/p/googleappengine/issues/detail?id=9173 – alex Apr 13 '13 at 16:27
  • s/MAX_INT/maximum integral precision using double representation/, as the other SO questions says JSON can't represent all arbitrary large integers using Number type. – proppy Apr 13 '13 at 16:28
  • Right.. so, I wanted to use integers for timestamps in millisec. I guess I'll have to just use ISO string format or something (the DateTimeField) – alex Apr 13 '13 at 16:30
  • Client libraries should do the right thing when receiving a large into field encoded as a string. – proppy Apr 13 '13 at 16:34
  • Damn I wish I had time to implement something like Endpoints in Go. gorilla/rpc seems to be moving in that direction. – alex Apr 13 '13 at 17:00
  • 1
    @alex Seems your comment came true :) – bossylobster May 16 '13 at 15:22
  • 1
    @bossylobster :) yeah, I wrote that comment but couldn't get rid of the idea in my head. so after a couple days I started experimenting and... well, you know what I ended up doing hehe. BTW, I don't think I would've gone so far w/o your help so, thanks again! – alex May 16 '13 at 15:34

1 Answers1

3

I guess @proppy is right. Also, it clearly states in the discovery format that

A 32-bit signed integer ("integer" type, int32 format). It has a minimum value of -2,147,483,648 and a maximum value of 2,147,483,647 (inclusive)

and

A 32-bit unsigned integer ("integer" type, uint32 format). It has a minimum value of 0 and a maximum value of 4,294,967,295 (inclusive).

All other kinds of int/bigint/whatever values are repesented as "string" types with different formats. More info: https://developers.google.com/discovery/v1/type-format

So, 1234567890123 number cannot in fact be represented in "integer" type. It's just the dev server doesn't convert integers to strings automatically (like the production infrastructure does), and I didn't realize how big the number was while testing locally.

It turns out a team at Google is already working on making it consistent: https://code.google.com/p/googleappengine/issues/detail?id=9173

alex
  • 2,450
  • 16
  • 22
  • Yes. Some changes to `protorpc` have been added (http://google-protorpc-review.appspot.com/93001/) to ensure this behavior is consistent. – bossylobster May 16 '13 at 15:22