Как сделать так чтобы objectMapper конвертировал объекты с final полями?

Рейтинг: 1Ответов: 2Опубликовано: 09.01.2023

Как сделать так чтобы objectMapper конвертировал объекты с final полями? У меня есть класс Answer:

public class Answer {
    private final String text;

    public Answer(String text) {
        this.text = text;
    }

    public String getText() {
        return text;
    }

    @Override
    public String toString() {
        return text;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof Answer) {
            String s = ((Answer) obj).getText();
            return this.text.equals(s);
        }
        return false;
    }
}

И класс Reading:

public class Reading {

    private Answer trueAnswer;

    @Override
    public String toString() {
        return "Reading{" +
                "text=" + trueAnswer +
                '}';
    }

    public Answer getTrueAnswer() {
        return trueAnswer;
    }

    public void setTrueAnswer(Answer trueAnswer) {
        this.trueAnswer = trueAnswer;
    }

    public Reading() {
    }

    public Reading(Answer text) {
        this.trueAnswer = text;
    }
}

А также json файл

{
  "trueAnswer": {
    "text": "Answer1|1"
  }
}

И класс Main для их реализации

public class Main {
    public static void main(String[] args) throws IOException {
        try {
            ObjectMapper mapper = new ObjectMapper();
          
            Reading reading = mapper.readValue(Paths.get("src/main/resources/read.json").toFile(), Reading.class);
            System.out.println(reading);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

Я хочу чтобы мой ObjectMapper сконвертировал содержимое json файла, но это не получается сделать так как в классе Answer нету пустого конструктора и я не могу его создать так как поля объявлены как final

Ответы

▲ 1Принят

Пробуйте так:

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;

public class Answer {

    private final String text;

    @JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
    public Answer(@JsonProperty("text") String text) {
        this.text = text;
    }

    public String getText() {
        return text;
    }

    @Override
    public String toString() {
        return text;
    }

    @Override
    public boolean equals(Object obj) {
        if (obj instanceof Answer) {
            String s = ((Answer) obj).getText();
            return this.text.equals(s);
        }
        return false;
    }
}
▲ 0

Два варианта

Десериализация с помощью конструктора

@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
public Answer(@JsonProperty("text") String text) {
    this.text = text;
}

Десериализация с помощью Builder-а

@JsonDeserialize(builder = Answer.Builder.class)
public class Answer {
  // тут все как и раньше
    
  @JsonPOJOBuilder
  static class Builder {
    String text;
    
    Builder withText(String text) {
        this.text = text;
        return this;
    }
    
    public Answer build() {
        return new Answer(text);
    } 
  }
}