IntegerField()在JSON中转换为任何数字的字符串

JLD*_*iaz 0 python google-app-engine json google-cloud-endpoints

这个问题很相似,这其中,只有更差......在我的测试,因此即使是很小的整数1转换为字符串.这是我的MWE:

app.yaml

application: your-app-id
version: 1
runtime: python27
threadsafe: true
api_version: 1

handlers:
- url: /_ah/spi/.*
  script: example.app
  secure: always

libraries:
- name: endpoints
  version: 1.0
Run Code Online (Sandbox Code Playgroud)

example.py

import endpoints
from protorpc import messages
from protorpc import message_types
from protorpc import remote

package = 'Example'

class Number(messages.Message):
    number = messages.IntegerField(1)

@endpoints.api(name='example', version='v1')
class ExampleApi(remote.Service):
    @endpoints.method(message_types.VoidMessage, Number,
            path = "getNumber", http_method='GET', name = 'getNumber')
    def get_number(self, _):
        return Number(number = 3)  # This is a small integer. Isn't?

app = endpoints.api_server([ExampleApi])
Run Code Online (Sandbox Code Playgroud)

测试

$ curl http://localhost:8080/_ah/api/example/v1/getNumber
{
 "number": "3"
}
Run Code Online (Sandbox Code Playgroud)

为什么?不应该是{ "number": 3 }吗?如果我想用它们算术,这迫使我在客户端重新转换我的所有整数.

(使用GAE SDK版本测试1.9.21 - 2015-05-12,在Linux和OSX中使用"native"dmg.编辑:还在生产中测试,部署在GAE服务器中,相同的结果...整数作为字符串接收)

更新

即使我的简单示例将整数作为字符串返回(如上所示),Google自己的API也不会这样做.他们做对了.例如,使用books apivia API探测器,在这里:

https://apis-explorer.appspot.com/apis-explorer/#p/books/v1/books.volumes.list?q=Google&_h=8&

你得到一个包含正确编码的整数的JSON答案,例如:

{
 "kind": "books#volumes",
 "totalItems": 551,
 "items": [ ... ]
  ...
}
Run Code Online (Sandbox Code Playgroud)

所以他们的API正在返回好的json.为什么我的API使用相同的工具(或者可能不是?),将整数作为字符串返回?我认为这是一个错误.

Jos*_*h J 8

看起来IntegerField的默认变体是INT64,它被编码成一个字符串 EndpointsProtoJson.encode_field

def encode_field(self, field, value):
    """Encode a python field value to a JSON value.

    Args:
      field: A ProtoRPC field instance.
      value: A python value supported by field.

    Returns:
      A JSON serializable value appropriate for field.
    """


    if (isinstance(field, messages.IntegerField) and
        field.variant in (messages.Variant.INT64,
                          messages.Variant.UINT64,
                          messages.Variant.SINT64)):
      if value not in (None, [], ()):

        if isinstance(value, list):
          value = [str(subvalue) for subvalue in value]
        else:
          value = str(value)
        return value
Run Code Online (Sandbox Code Playgroud)

您可以通过将其指定为messages.Message子类中的32位整数来更改此行为.

class Number(messages.Message):
    number = messages.IntegerField(1, variant=messages.Variant.INT32)
Run Code Online (Sandbox Code Playgroud)

  • 谢谢!显然这种行为是在2014年6月6日引入的(https://code.google.com/p/googleappengine/issues/detail?id=9173),这就是为什么[这个其他问题](http://stackoverflow.com/questions/15985069/integerfield-value-gets-converted-to-a-string-for-some-numbers)从2013年开始只针对大整​​数来解决这个问题(事实上,看起来这是由Alex引起的这个问题)修复"导致我的问题".圈子关闭:-) (2认同)