Uploaded image for project: 'Java Driver'
  1. Java Driver
  2. JAVA-2872

Provide an extension point for injecting a custom PropertySerialization implementation

    • Type: Icon: New Feature New Feature
    • Resolution: Unresolved
    • Priority: Icon: Major - P3 Major - P3
    • None
    • Affects Version/s: None
    • Component/s: POJO
    • Labels:
      None

      I have fields of type java.util.Optional in my POJOs, and I would like to avoid serialising the field if the value is an empty Optional.

      It looks like I can do this using a custom implementation of PropertySerialization, but as far as I can tell there is no easy way to inject my custom implementation when using the PojoCodecProvider.

      The only way I have found to do this is with some nasty reflection hackery, abusing a Convention to overwrite the propertySerialization field in all the PropertyModel s of the ClassModelBuilder:

      class MyConvention implements Convention {
      
          private PropertySerialization<?> optionalAwarePropertySerialization = 
              new OptionalAwarePropertySerialization();
      
          @Override
          public void apply(ClassModelBuilder<?> classModelBuilder) {
              try {
                  Class<PropertyModelBuilder> clazz = PropertyModelBuilder.class;
                  Field propertySerialization = clazz.getDeclaredField("propertySerialization");
                  propertySerialization.setAccessible(true);
                  for (PropertyModelBuilder<?> propertyModelBuilder: classModelBuilder.getPropertyModelBuilders()) {
                      propertySerialization.set(propertyModelBuilder, optionalAwarePropertySerialization);
                  }
              } catch (NoSuchFieldException | IllegalAccessException e) {
                  // error logging
              }
          }
      
      }
      

      I then register this convention when building the codec registry:

      CodecRegistry codecRegistry = CodecRegistries.fromRegistries(
                  MongoClient.getDefaultCodecRegistry(),
                  CodecRegistries.fromProviders(
                          PojoCodecProvider.builder()
                                  .automatic(true)
                                  .conventions(Arrays.asList(CLASS_AND_PROPERTY_CONVENTION, ANNOTATION_CONVENTION, new MyConvention()))
                                  .build()));
      

      This works, i.e. the property is not written to the Mongo document if it is empty, and it is passed to the POJO constructor as null when reading back from Mongo. But I have trouble sleeping at night knowing this code is running in production

            Assignee:
            Unassigned Unassigned
            Reporter:
            cb372 Chris Birchall
            Votes:
            1 Vote for this issue
            Watchers:
            4 Start watching this issue

              Created:
              Updated: