jazzband / jsonmodels

jsonmodels is library to make it easier for you to deal with structures that are converted to, or read from JSON.
http://jsonmodels.readthedocs.org/en/latest/
BSD 3-Clause "New" or "Revised" License
334 stars 51 forks source link

field of any object type // null #124

Open user706 opened 5 years ago

user706 commented 5 years ago

Hi,

thanks for this nice lib.

Question 1: Am I correct in assuming that to create a field for any type, I'll have to subclass fields.BaseField? See AnyField below.

from jsonmodels import models, fields, validators
import json

class AnyField(fields.BaseField):

    """Any field."""

    types = (object,)

    def parse_value(self, value):
        """Cast value to `bool`."""
        parsed = super(AnyField, self).parse_value(value)
        return parsed

class Whatever(models.Base):
    whatever = AnyField(default=None)

w = Whatever(**json.loads('{"whatever" : ["a", "b", "c"]}'))
print(json.dumps(w.to_struct()))

w = Whatever(**json.loads('{"whatever" : "asdf"}'))
print(json.dumps(w.to_struct()))

w = Whatever(**json.loads('{"whatever" : "asdf"}'))
print(json.dumps(w.to_struct()))

w = Whatever(**json.loads('{"whatever" : null}'))  
print(json.dumps(w.to_struct()))                              # XXX

w = Whatever()
print(json.dumps(w.to_struct()))

Question 2: Please see line marked with # XXX above. Is there any way
to get that printed as {"whatever" : null} ? What would I need to change? (Are there any settings I missed?)

Basically I want it to print the same as this...

import json
print(json.dumps({'whatever' : None}))

# prints:   {"whatever": null}

Or do you reserve None as a special marker? (If so, could that marker be changed
to class NoneMarker: pass. But what would that mean for compatibility and upgrades, for other people...?)

Thanks. Regards, user706

comic31 commented 5 years ago

Hi, You can override to_struct method in your model, check if your value is None and do some stuff.

     def to_struct(self):
        self.validate()
        resp = {}

        for _, name, field in self.iterate_with_name():
            value = field.__get__(self)
            _type = type(field)
            if value is None:
                resp[name] = None
            else:
                value = field.to_struct(value)
                resp[name] = value
        return resp