简体   繁体   English

GCP Proto Datastore 在 base64 中编码 JsonProperty

[英]GCP Proto Datastore encode JsonProperty in base64

I store a blob of Json in the datastore using JsonProperty .我使用JsonProperty在数据存储中存储了一个 Json 的 blob。 I don't know the structure of the json data.我不知道json数据的结构。

I am using endpoints proto datastore in order to retrieve my data.我正在使用endpoints proto datastore来检索我的数据。

The probleme is the json property is encoded in base64 and I want a plain json object.问题是 json 属性是用 base64 编码的,我想要一个普通的 json 对象。

For the example, the json data will be:例如,json 数据将是:

{
    first: 1,
    second: 2
}

My code looks something like:我的代码看起来像:

import endpoints
from google.appengine.ext import ndb
from protorpc import remote
from endpoints_proto_datastore.ndb import EndpointsModel


class Model(EndpointsModel):
    data = ndb.JsonProperty()


@endpoints.api(name='myapi', version='v1', description='My Sample API')
class DataEndpoint(remote.Service):

    @Model.method(path='mymodel2', http_method='POST',
                  name='mymodel.insert')
    def MyModelInsert(self, my_model):
        my_model.data = {"first": 1, "second": 2}
        my_model.put()
        return my_model

    @Model.method(path='mymodel/{entityKey}',
                  http_method='GET',
                  name='mymodel.get')
    def getMyModel(self, model):
        print(model.data)
        return model


API = endpoints.api_server([DataEndpoint])

When I call the api for getting a model, I get:当我调用 api 获取模型时,我得到:

POST /_ah/api/myapi/v1/mymodel2
{
    "data": "eyJzZWNvbmQiOiAyLCAiZmlyc3QiOiAxfQ=="
}

where eyJzZWNvbmQiOiAyLCAiZmlyc3QiOiAxfQ== is the base64 encoded of {"second": 2, "first": 1}其中eyJzZWNvbmQiOiAyLCAiZmlyc3QiOiAxfQ=={"second": 2, "first": 1}的 base64 编码

And the print statement give me: {u'second': 2, u'first': 1}打印语句给了我: {u'second': 2, u'first': 1}

So, in the method, I can explore the json blob data as a python dict .因此,在该方法中,我可以将 json blob 数据作为 python dict进行探索。 But, in the api call, the data is encoded in base64.但是,在 api 调用中,数据以 base64 编码。

I expeted the api call to give me:我加速了 api 调用给我:

{
    'data': {
        'second': 2,
        'first': 1
     }
}

How can I get this result?我怎样才能得到这个结果?

After the discussion in the comments of your question, let me share with you a sample code that you can use in order to store a JSON object in Datastore (it will be stored as a string), and later retrieve it in such a way that:在您问题的评论中进行讨论后,让我与您分享一个示例代码,您可以使用该代码将 JSON 对象存储在 Datastore 中(它将存储为字符串),然后以这样的方式检索它:

  • It will show as plain JSON after the API call.它将在 API 调用后显示为纯 JSON。
  • You will be able to parse it again to a Python dict using eval .您将能够使用eval再次将其解析为 Python dict。

I hope I understood correctly your issue, and this helps you with it.我希望我正确理解了您的问题,这对您有所帮助。

import endpoints
from google.appengine.ext import ndb
from protorpc import remote
from endpoints_proto_datastore.ndb import EndpointsModel

class Sample(EndpointsModel):
  column1 = ndb.StringProperty()
  column2 = ndb.IntegerProperty()
  column3 = ndb.StringProperty()

@endpoints.api(name='myapi', version='v1', description='My Sample API')
class MyApi(remote.Service):
  # URL: .../_ah/api/myapi/v1/mymodel - POSTS A NEW ENTITY
  @Sample.method(path='mymodel', http_method='GET', name='Sample.insert')
  def MyModelInsert(self, my_model):
    dict={'first':1, 'second':2}
    dict_str=str(dict)

    my_model.column1="Year"
    my_model.column2=2018
    my_model.column3=dict_str
    my_model.put()
    return my_model

  # URL: .../_ah/api/myapi/v1/mymodel/{ID} - RETRIEVES AN ENTITY BY ITS ID
  @Sample.method(request_fields=('id',), path='mymodel/{id}', http_method='GET', name='Sample.get')
  def MyModelGet(self, my_model):
    if not my_model.from_datastore:
      raise endpoints.NotFoundException('MyModel not found.')

    dict=eval(my_model.column3)
    print("This is the Python dict recovered from a string: {}".format(dict))

    return my_model

application = endpoints.api_server([MyApi], restricted=False)

I have tested this code using the development server, but it should work the same in production using App Engine with Endpoints and Datastore.我已经使用开发服务器测试了这段代码,但它应该在使用 App Engine 与端点和数据存储的生产中工作相同。

After querying the first endpoint, it will create a new Entity which you will be able to find in Datastore, and which contains a property column3 with your JSON data in string format:查询第一个端点后,它将创建一个新实体,您可以在 Datastore 中找到该实体,该实体包含一个属性column3 ,其中包含字符串格式的 JSON 数据:

在此处输入图片说明

Then, if you use the ID of that entity to retrieve it, in your browser it will show the string without any strange encoding, just plain JSON:然后,如果您使用该实体的 ID 来检索它,它会在您的浏览器中显示没有任何奇怪编码的字符串,只是普通的 JSON:

在此处输入图片说明

And in the console, you will be able to see that this string can be converted to a Python dict (or also a JSON, using the json module if you prefer):在控制台中,您将能够看到此字符串可以转换为 Python dict(或者也可以转换为 JSON,如果您愿意,可以使用json模块):

在此处输入图片说明

I hope I have not missed any point of what you want to achieve, but I think all the most important points are covered with this code: a property being a JSON object, store it in Datastore, retrieve it in a readable format, and being able to use it again as JSON/dict.我希望我没有遗漏您想要实现的任何一点,但我认为所有最重要的点都包含在这段代码中:属性是一个 JSON 对象,将它存储在 Datastore 中,以可读格式检索它,并且能够再次使用它作为 JSON/dict。


Update:更新:

I think you should have a look at the list of available Property Types yourself, in order to find which one fits your requirements better.我认为您应该自己查看可用的属性类型列表,以便找到更符合您要求的属性类型 However, as an additional note, I have done a quick test working with a StructuredProperty (a property inside another property), by adding these modifications to the code:但是,作为附加说明,我通过将这些修改添加到代码中,对StructuredProperty (另一个属性中的属性)进行了快速测试:

#Define the nested model (your JSON object)
class Structured(EndpointsModel):
  first = ndb.IntegerProperty()
  second = ndb.IntegerProperty()

#Here I added a new property for simplicity; remember, StackOverflow does not write code for you :)
class Sample(EndpointsModel):
  column1 = ndb.StringProperty()
  column2 = ndb.IntegerProperty()
  column3 = ndb.StringProperty()
  column4 = ndb.StructuredProperty(Structured)

#Modify this endpoint definition to add a new property
@Sample.method(request_fields=('id',), path='mymodel/{id}', http_method='GET', name='Sample.get')
  def MyModelGet(self, my_model):
    if not my_model.from_datastore:
      raise endpoints.NotFoundException('MyModel not found.')

    #Add the new nested property here
    dict=eval(my_model.column3)
    my_model.column4=dict
    print(json.dumps(my_model.column3))
    print("This is the Python dict recovered from a string: {}".format(dict))

    return my_model

With these changes, the response of the call to the endpoint looks like:通过这些更改,对端点的调用响应如下所示:

在此处输入图片说明

Now column4 is a JSON object itself (although it is not printed in-line, I do not think that should be a problem.现在column4本身就是一个 JSON 对象(虽然它不是内联打印的,但我认为这不应该是一个问题。

I hope this helps too.我希望这也有帮助。 If this is not the exact behavior you want, maybe should play around with the Property Types available, but I do not think there is one type to which you can print a Python dict (or JSON object) without previously converting it to a String.如果这不是您想要的确切行为,也许应该使用可用的属性类型,但我认为没有一种类型可以打印 Python dict(或 JSON 对象)而无需事先将其转换为字符串。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM