Utilisation de @JsonComponent dans Spring Boot

Utilisation de @JsonComponent dans Spring Boot

1. Vue d'ensemble

Cet article rapide est axé sur l'utilisation de l'annotation@JsonComponent dans Spring Boot.

L'annotation nous permet d'exposer une classe annotée en tant que sérialiseur et / ou désérialiseur Jackson sans avoir besoin de l'ajouter manuellement auxObjectMapper.

Cela fait partie du module principal Spring Boot, de sorte qu'aucune dépendance supplémentaire n'est requise dans une application Spring Boot standard.

2. La sérialisation

Commençons par l'objetUser suivant contenant une couleur préférée:

public class User {
    private Color favoriteColor;

    // standard getters/constructors
}

Si nous sérialisons cet objet en utilisant Jackson avec les paramètres par défaut, nous obtenons:

{
  "favoriteColor": {
    "red": 0.9411764740943909,
    "green": 0.9725490212440491,
    "blue": 1.0,
    "opacity": 1.0,
    "opaque": true,
    "hue": 208.00000000000003,
    "saturation": 0.05882352590560913,
    "brightness": 1.0
  }
}

Nous pouvons rendre le JSON beaucoup plus condensé et lisible en imprimant simplement les valeurs RGB, par exemple, à utiliser en CSS.

Dans cette mesure, il suffit de créer une classe qui implémenteJsonSerializer:

@JsonComponent
public class UserJsonSerializer extends JsonSerializer {

    @Override
    public void serialize(User user, JsonGenerator jsonGenerator,
      SerializerProvider serializerProvider) throws IOException,
      JsonProcessingException {

        jsonGenerator.writeStartObject();
        jsonGenerator.writeStringField(
          "favoriteColor",
          getColorAsWebColor(user.getFavoriteColor()));
        jsonGenerator.writeEndObject();
    }

    private static String getColorAsWebColor(Color color) {
        int r = (int) Math.round(color.getRed() * 255.0);
        int g = (int) Math.round(color.getGreen() * 255.0);
        int b = (int) Math.round(color.getBlue() * 255.0);
        return String.format("#%02x%02x%02x", r, g, b);
    }
}

Avec ce sérialiseur, le JSON résultant a été réduit à:

{"favoriteColor":"#f0f8ff"}

En raison de l'annotation@JsonComponent, le sérialiseur est enregistré dans les JacksonObjectMapper de l'application Spring Boot. Nous pouvons tester cela avec le test JUnit suivant:

@JsonTest
@RunWith(SpringRunner.class)
public class UserJsonSerializerTest {

    @Autowired
    private ObjectMapper objectMapper;

    @Test
    public void testSerialization() throws JsonProcessingException {
        User user = new User(Color.ALICEBLUE);
        String json = objectMapper.writeValueAsString(user);

        assertEquals("{\"favoriteColor\":\"#f0f8ff\"}", json);
    }
}

3. Désérialisation

En continuant avec le même exemple, nous pouvons écrire un désérialiseur qui transformera la couleur WebString en un objet JavaFX Color:

@JsonComponent
public class UserJsonDeserializer extends JsonDeserializer {

    @Override
    public User deserialize(JsonParser jsonParser,
      DeserializationContext deserializationContext) throws IOException,
      JsonProcessingException {

        TreeNode treeNode = jsonParser.getCodec().readTree(jsonParser);
        TextNode favoriteColor
          = (TextNode) treeNode.get("favoriteColor");
        return new User(Color.web(favoriteColor.asText()));
    }
}

Testons le nouveau désérialiseur et assurez-vous que tout fonctionne comme prévu:

@JsonTest
@RunWith(SpringRunner.class)
public class UserJsonDeserializerTest {

    @Autowired
    private ObjectMapper objectMapper;

    @Test
    public void testDeserialize() throws IOException {
        String json = "{\"favoriteColor\":\"#f0f8ff\"}"
        User user = objectMapper.readValue(json, User.class);

        assertEquals(Color.ALICEBLUE, user.getFavoriteColor());
    }
}

4. Serializer etDeserializer dans une classe

Lorsque vous le souhaitez, nous pouvons connecter le sérialiseur et le désérialiseur dans une classe en utilisant deux classes internes et en ajoutant les@JsonComponent sur la classe englobante:

@JsonComponent
public class UserCombinedSerializer {

    public static class UserJsonSerializer
      extends JsonSerializer {

        @Override
        public void serialize(User user, JsonGenerator jsonGenerator,
          SerializerProvider serializerProvider) throws IOException,
          JsonProcessingException {

            jsonGenerator.writeStartObject();
            jsonGenerator.writeStringField(
              "favoriteColor", getColorAsWebColor(user.getFavoriteColor()));
            jsonGenerator.writeEndObject();
        }

        private static String getColorAsWebColor(Color color) {
            int r = (int) Math.round(color.getRed() * 255.0);
            int g = (int) Math.round(color.getGreen() * 255.0);
            int b = (int) Math.round(color.getBlue() * 255.0);
            return String.format("#%02x%02x%02x", r, g, b);
        }
    }

    public static class UserJsonDeserializer
      extends JsonDeserializer {

        @Override
        public User deserialize(JsonParser jsonParser,
          DeserializationContext deserializationContext)
          throws IOException, JsonProcessingException {

            TreeNode treeNode = jsonParser.getCodec().readTree(jsonParser);
            TextNode favoriteColor = (TextNode) treeNode.get(
              "favoriteColor");
            return new User(Color.web(favoriteColor.asText()));
        }
    }
}

5. Conclusion

Ce tutoriel rapide a montré comment ajouter rapidement un sérialiseur / désérialiseur Jackson dans une application Spring Boot en tirant parti de l'analyse des composants avec l'annotation@JsonComponent.

Les extraits de code peuvent être trouvésover on GitHub.