Coder Social home page Coder Social logo

Comments (10)

sloria avatar sloria commented on August 19, 2024

Odd indeed. Do you see the correct output when you explicitly specify the field type for contact_id?

class EventSerializer(Serializer):
    action = fields.Method('action_to_text')
    type = fields.Method('type_to_text')
    event_id = fields.Integer(attribute='id')
    contact_id = fields.Integer()
    # ...

from marshmallow.

ScottSturdivant avatar ScottSturdivant commented on August 19, 2024

Unfortunately, no, the second element still has 0 instead of None even when explicitly specifying the field type.

from marshmallow.

sloria avatar sloria commented on August 19, 2024

What type of object is an event?

from marshmallow.

ScottSturdivant avatar ScottSturdivant commented on August 19, 2024

Hi there,

Thanks for your patience, I was able to come up with a simple example that demonstrates the problem.

class Foo(object):
    def __init__(self, id, other):
        self.id = id
        self.other_id = other

 class FooSerializer(Serializer):
     class Meta:
         fields = ['id', 'other_id']

Serialized singularly, with 'other_id' not set:

>>> FooSerializer(Foo(1,None)).data
OrderedDict([('id', 1), ('other_id', None)])

When multiple, with 'other_id' set in one, but not in another:

>>> lots_of_foo = [Foo(1,1), Foo(1,None)]
>>> FooSerializer(lots_of_foo, many=True).data
[OrderedDict([('id', 1), ('other_id', 1)]), OrderedDict([('id', 1), ('other_id', 0)])]

For what it's worth, changing the order (putting the instance with None in it first), results in correct serialization:

>>> lots_of_foo = [Foo(1,None), Foo(1,1), Foo(2,None)]
>>> FooSerializer(lots_of_foo, many=True).data
[OrderedDict([('id', 1), ('other_id', None)]), OrderedDict([('id', 1), ('other_id', 1)]), OrderedDict([('id', 2), ('other_id', None)])]

Hope that you're able to reproduce and that it helps track it down!

Thanks!

from marshmallow.

ScottSturdivant avatar ScottSturdivant commented on August 19, 2024

Sorry, here's an update with an even more simple example:

class Foo(object):
    def __init__(self, id):
        self.id = id

class FooSerializer(Serializer):
    class Meta:
        fields =['id']

 >>>  FooSerializer([Foo(None), Foo(1)], many=True).data
 [OrderedDict([('id', None)]), OrderedDict([('id', 1)])]

 >>> FooSerializer([Foo(1), Foo(None)], many=True).data
 [OrderedDict([('id', 1)]), OrderedDict([('id', 0)])]

from marshmallow.

sloria avatar sloria commented on August 19, 2024

Oh, I see now. When you use Meta.fields option without explicitly declaring a field on the class, there is no way for the Serializer to "know" what Field class to use for serializing id until you serialize the first object in the list.

When you use implicit field creation (i.e. Meta.fields with no explicit field declaration) together with many=True, the Serializer will inspect the first element of the list to serialize and choose which Field classes to use according to this mapping: https://github.com/sloria/marshmallow/blob/4e14f192ac478f0f0a46c671a53dc55fc5831c41/marshmallow/serializer.py#L113-127 .

Because the first Foo in the list has an id of None, the Serializer defaults to using the Raw field to format id.

The fix here is to use explicit field declaration for the id field.

from marshmallow import Serializer, fields

class Foo(object):
    def __init__(self, id):
        self.id = id

class FooSerializer(Serializer):
    id = fields.Integer()
    class Meta:
        fields =['id']

FooSerializer([Foo(None), Foo(1)], many=True).data
# [OrderedDict([('id', 0)]), OrderedDict([('id', 1)])]

Hope that helps!

from marshmallow.

ScottSturdivant avatar ScottSturdivant commented on August 19, 2024

Hey, sorry for being a bit slow here, but even in that case, it's not giving the result I might expect (that the value for 'id' in the first element is None, not 0.

My real class looks like:

class Event(db.Model):
    id = db.Column(db.Integer, nullable=True)

Since I didn't declare an explicit field type, and because of the ordering of my data, it chose a 'Raw' field type. But it really is an Integer, and is nullable, and instead of returning 0, I'd like it to just return None.

Should I just make my own NullableInteger field type?

class NullableInteger(fields.Raw):
    def format(self, value):
        if value is None:
            return value
        return int(value)

class FooSerializer(Serializer):
    id = NullableInteger()
    class Meta:
        fields =['id']

FooSerializer([Foo(None), Foo(1)], many=True).data
# [OrderedDict([('id', None)]), OrderedDict([('id', 1)])]

Thanks...going ahead and closing this issue since it's definitely just my misunderstanding!

from marshmallow.

sloria avatar sloria commented on August 19, 2024

You should just be able to set default=None if you want None to serialize to None.

class FooSerializer(Serializer):
    id = fields.Integer(default=None)
    class Meta:
        fields =['id']

from marshmallow.

ScottSturdivant avatar ScottSturdivant commented on August 19, 2024

Indeed, that works great. Sorry for all of the noise!

from marshmallow.

sloria avatar sloria commented on August 19, 2024

No need to apologize. Happy I could help!

from marshmallow.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.