Spring rest xml dateTime format

2019-07-17 10:49发布

问题:

We use SpringBoot with Spring Rest and Jackson. We use Java 8 LocalDateTime.

RestController.

@RestController
@RequestMapping(method = RequestMethod.GET, produces = {MediaType.APPLICATION_XML_VALUE, MediaType.APPLICATION_JSON_VALUE})
public class SimpleRestController {

    @Autowired
    private RestService restService;

    @RequestMapping("/api/{id}")
    public ResponseEntity<RestObject> getModel(@PathVariable Long id) {
        RestObject restObject = restService.getModel(id);
        HttpStatus httpStatus = HttpStatus.OK;

        if (restObject == null) {
            httpStatus = HttpStatus.NO_CONTENT;
        }

        return new ResponseEntity<>(restObject, httpStatus);
    }
}

RestObject to be returned by the controller.

import javax.xml.bind.annotation.XmlRootElement;
import java.io.Serializable;
import java.time.LocalDateTime;

@XmlRootElement
public class RestObject implements Serializable {

    private LocalDateTime timestamp;
    private String title;
    private String fullText;
    private Long id;
    private Double value;

    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    public LocalDateTime getTimestamp() {
        return timestamp;
    }

    //Other getters and setters.
}

It works well when I send a GET request with Accept=application/json header. This is the response.

{
  "timestamp": "2017-06-09 15:58:32",
  "title": "Rest object",
  "fullText": "This is the full text. ID: 10",
  "id": 10,
  "value": 0.22816149915219197
}

However Accept=application/xml:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<restObject>
    <fullText>This is the full text. ID: 10</fullText>
    <id>10</id>
    <timestamp/>
    <title>Rest object</title>
    <value>0.15697306201038086</value>
</restObject>

Timestamp field is empty. How to make it work?

回答1:

Here comes the solution!

This is the response

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<restObject>
    <fullText>This is the full text. ID: 10</fullText>
    <id>10</id>
    <timestamp>2017-06-09 16:31:01</timestamp>
    <title>Rest object</title>
    <value>0.0021564103099468435</value>
</restObject>

1) Add class DateTimeAdapter

import javax.xml.bind.annotation.adapters.XmlAdapter;
import java.time.LocalDateTime;

public class DateTimeAdapter extends XmlAdapter<String, LocalDateTime> {

    public static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
    public static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern(DATE_FORMAT);

    public LocalDateTime unmarshal(String v) throws Exception {
        return LocalDateTime.parse(v, DATE_TIME_FORMATTER);
    }

    public String marshal(LocalDateTime v) throws Exception {
        return DATE_TIME_FORMATTER.format(v);
    }
}

2) Update RestObject class. Add @XmlJavaTypeAdapter(DateTimeAdapter.class) annotation on the LocalDateTime field.

import com.ca.training.rest.server.config.DateTimeAdapter;
import com.fasterxml.jackson.annotation.JsonFormat;

import javax.xml.bind.annotation.XmlRootElement;
import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
import java.io.Serializable;
import java.time.LocalDateTime;

import static com.ca.training.rest.server.config.DateTimeAdapter.DATE_FORMAT;

@XmlRootElement
public class RestObject implements Serializable {

    private LocalDateTime timestamp;
    private String title;
    private String fullText;
    private Long id;
    private Double value;

    @XmlJavaTypeAdapter(DateTimeAdapter.class)
    @JsonFormat(pattern = DATE_FORMAT)
    public LocalDateTime getTimestamp() {
        return timestamp;
    }

    //Other getters and setters.
}

I took the idea from here http://blog.bdoughan.com/2011/05/jaxb-and-joda-time-dates-and-times.html and here JAXB: Isn't it possible to use an XmlAdapter without @XmlJavaTypeAdapter?