Как изменить формат данных узла JSON при сериализации и десериализации в jackson

У меня есть следующий входящий json, который я десериализую в Model.java, а затем копирую этот java-объект в ModelView.java. Я не хочу конвертировать дату из строки в миллисекунды и отправлять исходящий json в качестве ответа. Как мне пойти на это?

У меня есть конкретная причина скопировать значение из Model.java в ModelView.java с помощью средства сопоставления объектов. Поэтому, пожалуйста, не предлагайте изменить эту часть. Я хочу сделать это с помощью аннотации. Я почти уверен, что это можно сделать, но не знаю, как.

Приведенный здесь json является упрощенным. У меня есть большой json в реальном сценарии.

Входящий json

{
 "date":"2016-03-31"
}

Исходящий JSON

{
 "date":236484625196
}

Мой класс контроллера

@Controller
public class SomeController extends BaseController {

    @Autowired
    private SomeService someService;


    @RequestMapping(method = RequestMethod.GET, produces = "application/json")
    public @ResponseBody
    ResponseEntity<RestResponse> getDetails(HttpServletRequest request, HttpServletResponse response) {

        Model model = someService.getData();

        ModelView modelView = ModelView.valueOf(model);

        return getSuccessResponse(modelView);
    }
}

Модель.java

@JsonInclude(Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
public class Model implements Serializable {

    private String date;

    //normal getters and setters
}

ModelView.java

@JsonInclude(Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
public class ModelView implements Serializable {

    private Long date;
    //normal getters and setters


    public static ModelView valueOf(Model model){
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-mm-dd");

        ObjectMapper mapper = new ObjectMapper();
        ModelView modelView =  mapper.convertValue(model, ModelView.class);
        try {

            modelView.setDate(sdf.parse(model.getDate()).getTime());
        } catch (ParseException e) {
            IntLogger.error("logging error here");
        }
        return modelView;
    }
}

Я готов изменить имя переменной с «дата» на что-то другое в ModelView.java, но исходящий json должен оставаться прежним.


person advaita    schedule 11.11.2016    source источник


Ответы (1)


У Джексона есть встроенное форматирование даты, например, вы можете установить DateFormatter в сопоставителе объектов, но я считаю, что это работает, только если формат сериализации и десериализации одинаков.

Более простой подход к сериализации и десериализации даты, если вы хотите, чтобы сериализация и десериализация были в другом формате, заключается в непосредственном использовании аннотаций @JsonSerialize и @JsonDeserialize в вашем Model.class (это может устареть необходимость в ModelView, если вашей единственной целью было преобразование Дата).

Вы можете создать два класса для сериализации и десериализации:

public class JsonDateDeserializer extends JsonDeserializer<Date> {

    @Override
    public Date deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
        final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        String dateString = jsonParser.getText();
        try {
            return dateFormat.parse(dateString);
        }
        catch (ParseException e) {
            throw new RuntimeException(e);
        }
    }
}

Затем для сериализации в исходящий json:

public class JsonDateSerializer extends JsonSerializer<Date> {

    @Override
    public void serialize(Date date, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
        jsonGenerator.writeString(Long.toString(date.getTime()));

    }
}

Теперь вы просто аннотируете свой Model.java:

@JsonInclude(Include.NON_NULL)
@JsonIgnoreProperties(ignoreUnknown = true)
public class Model implements Serializable {

    @JsonSerialize(using = JsonDateSerializer.class)
    @JsonDeserialize(using = JsonDateDeserializer.class)
    private String date;

    //normal getters and setters
}
person Andrew Phillips    schedule 11.11.2016
comment
Привет, @Andrew. Я последовал твоему совету по внедрению пользовательского сериализатора, но сделал это немного по-другому. Я изменил тип данных моего ModelView.java с Long на String и применил только сериализатор для этого поля. И в сериализаторе вместо jsonGenerator.writeString я использовал jsonGenerator.number и это сработало. - person advaita; 16.11.2016