Home > Blockchain >  Deserialize Json and move field to internal object
Deserialize Json and move field to internal object

Time:08-19

I'm trying to deserialize a Json object that looks like this:

{
  "score": 123
}

But I want to store it in an Object like this:

package com.torchai.service.informationunderstanding.domain;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;
import lombok.ToString;

@Getter
@Setter
@ToString
public class MyObject {

    private Scores scoreObject = new Scores();

    @JsonIgnore
    public double getScore() {
        return scoreObject.getScore();
    }

    public void setScore(final double score) {
        scoreObject.setScore(score);
    }

    @Getter
    @Setter
    @NoArgsConstructor
    @ToString
    public static class Scores {
        private double score;
    }

    public static void main(String[] args) throws JsonProcessingException {
        String json = "{ \"score\": 123 }";
        final ObjectMapper objectMapper = new ObjectMapper();
        final MyObject myObject = objectMapper.readValue(json, MyObject.class);
        System.out.println("*** myObject: "   myObject);
        System.out.println(objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString((myObject)));
    }
}

In other words, I don't have a score field. Instead, I want to store it in the inner Scores object.

I thought that by annotating getScore() with @JsonIgnore, that would cause Jackson to use the setter to set the field in the object. But when serializing back to Json, only the inner Scores object would be serialized, not the getter. But the output I get is this:

*** myObject: MyObject(scoreObject=MyObject.Scores(score=0.0))
{
  "scoreObject" : {
    "score" : 0.0
  }
}

The field is not being set correctly by the setter. If I comment out the @JsonIgnore on getScore(), then I get this

*** myObject: MyObject(scoreObject=MyObject.Scores(score=123.0))
{
  "scoreObject" : {
    "score" : 123.0
  },
  "score" : 123.0
}

The value is set correctly, but Jackson outputs the implicit score field from the getter, as well as the scoreObject.

How do I get the output to look like the first example, but with the correct value?

Note

I know that I could write a custom deserializer, but thought this was a simple enough case that I didn't need to do that.

CodePudding user response:

I think you can use JsonUnwrapped

@JsonUnwrapped
private Scores scoreObject = new Scores();

CodePudding user response:

If you want only the "primitive" score to show up in the JSON representation, then you should apply @JsonIgnore to scoreObject. Like this:


    @JsonIgnore
    private Scores scoreObject = new Scores();

    public double getScore() {
        return scoreObject.getScore();
    }

Note that the output will not be exactly like the original JSON; you are storing it as a double in the Scores class, so it will be output that way: { "score" : 123.0 }


If, on the other hand, your goal is for the serialized form to look like

{
  "scoreObject" : {
    "score" : 123.0
  }
}

then you need to annotate the setScore() method to tell Jackson where to deserialize the input value:

    private Scores scoreObject = new Scores();

    public Scores getScoreObject() {
        return scoreObject;
    }

    @JsonIgnore
    public double getScore() {
        return scoreObject.getScore();
    }

    @JsonProperty("score")
    public void setScore(final double score) {
        scoreObject.setScore(score);
    }

  • Related