Сериализация даты в веб-службе JSON REST как строка ISO-8601

У меня есть приложение JAX-RS с использованием JBoss AS 7.1 и я POST/GET JSON и объекты XML, которые включают Dates (java.util.Date):

@XmlRootElement
@XmlAccessorType(XmlAccessField.FIELD)
public class MyObject implements Serializable
{
    @XmlSchemaType(name = "dateTime")
    private Date date;
    ...
}

Когда я использую @produce ( "application/xml" ) в методе get, объекты задаются как XML и даты преобразуются в строки ISO-8601 (например, "2012-12-10T14: 50: 12.123 + 02:. 00" )

Однако, если я использую @Produce ( "application/json" ) в методе get, даты в объектах JSON являются метками времени (например, "1355147452530" ) вместо строк ISO-8601.

Как мне настроить JAX-RS (RESTEasy) для сериализации дат в формате JSON как строки ISO-8601 вместо временных меток?

Спасибо за ваши ответы.

Примечание. Я также попытался использовать собственный поставщик JAX-RS для сериализации JSON для дат

@Provider
@Produces(MediaType.APPLICATION_JSON)
public class CustomJsonDateProvider implements MessageBodyWriter<Date>
{
    ...
}

Этот провайдер, похоже, зарегистрирован RESTeasy при запуске JBoss:

[org.jboss.jaxrs] Adding JAX-RS provider classes: package.CustomJsonDateProvider
...
[org.jboss.resteasy.cdi.CdiInjectorFactory] No CDI beans found for class package.CustomJsonDateProvider. Using default ConstructorInjector.

но он никогда не используется!

Ответы

Ответ 1

Я предполагаю, что ваш json-парсер - Jackson, попробуйте:

@JsonFormat(shape=JsonFormat.Shape.STRING, pattern="yyyy-MM-dd,HH:00", timezone="CET")
public Date date;

(начиная с Jackson 2.0)

Ответ 2

Парсер JBoss по умолчанию - Jettison, но я не смог изменить формат даты. Поэтому я переключился на Jackson и добавил в свой проект следующий класс:

@Provider
@Produces(MediaType.APPLICATION_JSON)
public class JacksonConfig implements ContextResolver<ObjectMapper>
{
    private final ObjectMapper objectMapper;

    public JacksonConfig()
    {
        objectMapper = new ObjectMapper();
        objectMapper.configure(SerializationConfig.Feature.WRITE_DATES_AS_TIMESPAMPS, false);
    }

    @Override
    public ObjectMapper getContext(Class<?> objectType)
    {
        return objectMapper;
    }
}

Ответ 3

Извините, что люди кричали вслух - я нашел ответы здесь.

http://wiki.fasterxml.com/JacksonFAQDateHandling,

здесь

http://wiki.fasterxml.com/JacksonFAQ#Serializing_Dates,

здесь

http://wiki.fasterxml.com/JacksonHowToCustomSerializers

здесь

http://jackson.codehaus.org/1.1.2/javadoc/org/codehaus/jackson/map/util/StdDateFormat.html

Использование метода @JsonSerialize (using =...):

public class JsonStdDateSerializer
extends JsonSerializer<Date> {

  private static final DateFormat iso8601Format =
    StdDateFormat.getBlueprintISO8601Format();

  @Override
  public void serialize(
    Date date, JsonGenerator jgen, SerializerProvider provider)
  throws IOException, JsonProcessingException {

    // clone because DateFormat is not thread-safe
    DateFormat myformat = (DateFormat) iso8601Format.clone();
    String formattedDate = myformat.format(date);
    jgen.writeString(formattedDate);
  }
}