Polymer: Polymer 2 Enhancement: Custom Serializers and Deserializers.

Created on 11 May 2017  Â·  12Comments  Â·  Source: Polymer/polymer

Polymer 1 allowed you to override the serialize method (not too useful) but it appears that this functionality has been removed in v2. It would be very useful to be able to provide custom property/attribute serialization/deserialization for object and array properties. e.g. If you have a "margin" property, the value would be:

{
    top: 2,
    right: 4,
    bottom: 6,
    left: 8
}

This gets JSON serialized to the attribute like so (ugly):

margin='{ "top": 2, "right": 4, "bottom": 6, "left": 8 }'

I'd like to be able to provide custom functionality that's similar to the WPF type converters to map it to something like this:

margin="2, 4, 6, 8"

Looking at the Polymer source, there's a couple of ways of doing it. Class level functions that take a property/attribute name seems the simplest but I'm not sure if they'd play nicely with mixins that add properties. Adding the serializer/deserializer functions to the property definition itself seems the nicest to me:

margin: {
    type: Object,
    value: ....,
    reflectToAttribute: true,
    serialize: function () {...},
    deserialize: function () {...}
}

First prize would be for Polymer to properly use property types, then we could register global type converters:

margin: {
    type: Thickness,
    ...
}

class Thickness {
    // Define the left, right, top and bottom properties.
}

class ThicknessTypeConverter {
    serialize (attribute, value) {}
    deserialize (property, value) {}
}

// Register the converter somehow.

Or perhaps add the functionality to the type object itself (maybe have a "Serializable" base class):

class Thickness extends Serializable {
    // Define the left, right, top and bottom properties.
    serialize (attribute, value) {}
    deserialize (property, value) {}
}
2.x docs

Most helpful comment

Great! I also added this to the guides to make things a little clearer.

https://www.polymer-project.org/2.0/docs/devguide/properties#custom-deserializers

Note that Date is already handled automatically by Polymer—if you have a property specified as type: Date and you set the corresponding attribute to a string representation, Polymer creates a Date object for you, just like it creates an array from a JSON-encoded array.

All 12 comments

Hi Paul,

This have been removed, but it's been moved... Specifically, in keeping
with the new API standards, these are now "protected" methods,
_serializeValue and _deserializeValue.

I'll make sure this info gets added to the upgrade guide.

Thanks,
Arthur

I presume that means we shouldn't be overriding _serializeValue and _deserializeValue now? It would be good to be able to do that, and get the attribute/property name passed to the two methods as well.

Though I see your point in more complex datastructures where you want to deserialize in a specific manner, I do think margin is something that should exists in CSS, and be manipulated using CSS custom properties.

Sent on the go - just so so you know!

Den 12. maj 2017 kl. 10.02 skrev Paul Mason notifications@github.com:

I presume that means we shouldn't be overriding _serializeValue and _deserializeValue now? It would be good to be able to do that, and get the attribute/property name passed to the two methods as well.

—
You are receiving this because you are subscribed to this thread.
Reply to this email directly, view it on GitHub, or mute the thread.

@noahlaux The margin thing was just an example because it illustrates nicely how a data structure can be collapsed into a simpler attribute representation. Arrays of strings are probably a better example.

something='["one", "two", "three"]'

becomes

something="one, two, three"

I see your point, I just happen to like the array structure better, because
it uses javascript own natural way to describe a list, and as an added
bonus you can directly bind an array to that attribute and get expected
results. If I should end up with "one, two, three" and my starting point is
["one", "two", "three"] I'd have to join prior to binding, I don't see the
benefits, it's really just more work.

Kind Regards

Noah Laux
Senior Software Developer

[email protected] - (+45) 60 77 74 33
Skype: noahlaux // facebook.com/noahlaux // @noahlaux
http://twitter.com/noahlaux // last.fm/noahlaux

2017-05-12 10:19 GMT+02:00 Paul Mason notifications@github.com:

@noahlaux https://github.com/noahlaux The margin thing was just an
example because it illustrates nicely how a data structure can be collapsed
into a simpler attribute representation. Arrays of strings are probably a
better example.

something='["one", "two", "three"]'

becomes

something="one, two, three"

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
https://github.com/Polymer/polymer/issues/4592#issuecomment-301014654,
or mute the thread
https://github.com/notifications/unsubscribe-auth/AA1wb_0cm2jQ2jcJjV9WUa0ISNZIH_Ggks5r5BYGgaJpZM4NXgdT
.

+1
I'd specifically like custom deserialization (serialization would be good too).

Sometimes there is a property that I'd like to accept different possible input formats for but would like to have a single normalized value to work with internally.

  • I can deserialize/normalize via an observer, but then when my observer updates its own property value (with the normalized value) it will trigger the observer again and that is awkward and can cause bugs.
  • Instead I can have a computed property based off the other property value, but that seems like unnecessary clutter and the components public interface becomes confusing.
  • Are there better ways of doing this currently?

If I could do the deserialization myself then it would cleanup that logic. Deserialization would need to be invoked when the property is set directly as well as when it's set via its attribute.

Afaik in Polymer 2 any protected methods are meant to be able to be overridden or extended, and the less reliable to override or extend would be the private methods (2 underscores vs 1 for protected).

So it seems to me that you shouldn't have any problem with overriding these methods.

It'd be useful for Date objects. I'm working on a web app using Polymer and every data displayed is fetched from an API which returns data in JSON, thus dates are in text format. But in my components I'd like to have a Date object instead of a String so I can use the same base object for different uses :

  • Filtering (using string search with long format e.g. Saturday, May 13th, 2017)
  • Sorting (using string comparison with short format e.g. 2017-05-13)
  • Displaying to user (using whatever format you want)

This way I wouldn't need to create Date objects for formatting from the base String value every time I need to filter/sort nor to have multiple computed properties based on this String value.

Just found the doc about the _deserializeValue() method which solves the problem for me.

Great! I also added this to the guides to make things a little clearer.

https://www.polymer-project.org/2.0/docs/devguide/properties#custom-deserializers

Note that Date is already handled automatically by Polymer—if you have a property specified as type: Date and you set the corresponding attribute to a string representation, Polymer creates a Date object for you, just like it creates an array from a JSON-encoded array.

Note that it'd be easy to implement a scheme like @PaulHMason described like this:

_deserializeValue(value, type) {
  if (type && type.fromString) {
    return type.fromString(value);
  } else {
    return super._deserializeValue(value, type);
  }
}

Custom deserializing for arrays would be a little trickier, as you'd have to set the type to something other than Array. However, you can always use jsdoc comments to clarify the actual property type.

That doesn't help with serializing, since serializing is always based on the property's _current type_, not its declared type.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

SergRZ picture SergRZ  Â·  3Comments

dandv picture dandv  Â·  4Comments

paranoid-android picture paranoid-android  Â·  3Comments

yordis picture yordis  Â·  3Comments

hzmnet picture hzmnet  Â·  4Comments