5

I like how the JsonProperty automatically encodes a Python structure into JSON when the property is put into the data store, and automatically decodes it when retrieved. However, it would be nice to send that JSON data to a web browser without having to encode it again. Is there a way to get the raw JSON data (that is, prevent the decoding)?

class DataForBrowser(ndb.Models)
    json = ndb.JsonProperty()

    def get_json(self):
        return ???
Brent Washburne
  • 12,904
  • 4
  • 60
  • 82

1 Answers1

5

So what you want is to have a dict that gets encoded when saved to the datastore but not decoded upon retrieving it... What happens "under the hood" is that a JsonProperty is a subclass of BlobProperty that gets encoded (json.dumps()) every time it gets written to the datastore and decoded (json.loads()) every time it's read. This can be done only with a property subclass that eliminates one of these functions (but I don't think it's wise to have different behaviors for the property according to the state the entity is). Just for "educational purposes" let's see what will happen then

from google.appengine.ext import ndb
import json

class ExtendedJsonProperty(ndb.BlobProperty):
  def _to_base_type(self, value):
    return json.dumps(value) 

  def _from_base_type(self, value):
    return value
    # originally return json.loads(value)

class DataForBrowser(ndb.Model):
    json = ExtendedJsonProperty()


data = {'a': 'A'}
data_for_browser = DataForBrowser()
data_for_browser.json = data
print type(data_for_browser.json)  # returns <type 'dict'>
data_for_browser.put()
print type(data_for_browser.json) # returns <type 'str'>
data_for_browser_retrieverd = DataForBrowser.query().get()
print type(data_for_browser_retrieverd.json) # returns <type 'str'>

If you need to make use of the dict in your code then I suggest using a JsonProperty and adding a new property method that will return the dict as JSON and use that.

@property
def json_as_json(self):
  return json.dumps(self.json)

If you use the dict only to create the JSON data then just use a BlobProperty and pass through json.dumps() before assigning the data to the property

nizz
  • 1,133
  • 7
  • 16
  • 1
    Yes, that's similar to what I'm currently doing now. I'm wondering if there is a "back door" method (like a Hook method) that will simply return the JSON string from a `JsonProperty`. It seems like going backwards to introduce the `ExtendedJsonProperty`. – Brent Washburne Sep 03 '13 at 21:09
  • 1
    I don't think that this is possible since the _from_base_type() method is called right after the data is fetched from the datastore. From that point on, the original data isn't accessible anymore. – nizz Sep 04 '13 at 01:27
  • 1
    That's not the answer I wanted, but I think it's the correct answer. – Brent Washburne Sep 04 '13 at 05:10