Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/399.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 泽西岛+;Jackson JSON日期格式序列化-如何更改格式或使用自定义JacksonJsonProvider_Java_Serialization_Jersey_Jax Rs_Jackson - Fatal编程技术网

Java 泽西岛+;Jackson JSON日期格式序列化-如何更改格式或使用自定义JacksonJsonProvider

Java 泽西岛+;Jackson JSON日期格式序列化-如何更改格式或使用自定义JacksonJsonProvider,java,serialization,jersey,jax-rs,jackson,Java,Serialization,Jersey,Jax Rs,Jackson,我正在使用Jersey+Jackson为我的应用程序提供RESTJSON服务层。我遇到的问题是默认的日期序列化格式如下所示: "CreationDate":1292236718456 起初我以为这是一个UNIX时间戳。。。但这太长了。我的客户端JS库在反序列化这种格式时遇到问题(它支持多种不同的日期格式,但我想不是这种格式)。我想更改格式,以便我的库可以使用它(例如ISO)。我该怎么做。。。我找到了一段代码可以帮上忙但是。。。我应该把它放在哪里,因为我不控制Jackson序列化程序实例化(Je

我正在使用Jersey+Jackson为我的应用程序提供RESTJSON服务层。我遇到的问题是默认的日期序列化格式如下所示:

"CreationDate":1292236718456
起初我以为这是一个UNIX时间戳。。。但这太长了。我的客户端JS库在反序列化这种格式时遇到问题(它支持多种不同的日期格式,但我想不是这种格式)。我想更改格式,以便我的库可以使用它(例如ISO)。我该怎么做。。。我找到了一段代码可以帮上忙但是。。。我应该把它放在哪里,因为我不控制Jackson序列化程序实例化(Jersey控制)

我还为custom
JacksonJsonProvider找到了这段代码-问题是。。如何让我所有的POJO类都使用它

@Provider
public class MessageBodyWriterJSON extends JacksonJsonProvider {

    private static final String DF = "yyyy-MM-dd’T'HH:mm:ss.SSSZ";

    @Override
    public boolean isWriteable(Class arg0, Type arg1, Annotation[] arg2,
            MediaType arg3) {
        return super.isWriteable(arg0, arg1, arg2,
                arg3);
    }
    @Override
    public void writeTo(Object target, Class arg1, Type arg2, Annotation[] arg3,
            MediaType arg4, MultivaluedMap arg5, OutputStream outputStream)
            throws IOException, WebApplicationException {
            SimpleDateFormat sdf=new SimpleDateFormat(DF);

        ObjectMapper om = new ObjectMapper();
        om.getDeserializationConfig().setDateFormat(sdf);
        om.getSerializationConfig().setDateFormat(sdf);
        try {
            om.writeValue(outputStream, target);
        } catch (JsonGenerationException e) {
            throw e;
        } catch (JsonMappingException e) {
            throw e;
        } catch (IOException e) {
            throw e;
        }
    }
}

值得一提的是,这个数字是标准的Java时间戳(由JDK类使用);Unix存储秒,Java毫秒,这就是为什么它的值要大一点


我希望有一些关于如何将ObjectMapper注入Jersey的文档(它应该遵循注入所提供对象的常规方法)。但是,您也可以重写JacksonJaxRsProvider来指定/配置ObjectMapper并注册它;Jersey本身就是这样做的,有多种方法可以做到这一点。

要配置您自己的ObjectMapper,您需要注入实现ContextResolver的类

确切地说,如何让泽西队接手这项比赛将取决于你的国际奥委会(春季,guice)。我使用spring,我的类如下所示:

import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;

import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig.Feature;
import org.codehaus.jackson.map.deser.CustomDeserializerFactory;
import org.codehaus.jackson.map.deser.StdDeserializerProvider;
import org.codehaus.jackson.map.ser.CustomSerializerFactory;
import org.springframework.stereotype.Component;

// tell spring to look for this.
@Component
// tell spring it's a provider (type is determined by the implements)
@Provider
public class ObjectMapperProvider implements ContextResolver<ObjectMapper> {
    @Override
    public ObjectMapper getContext(Class<?> type) {
        // create the objectMapper.
        ObjectMapper objectMapper = new ObjectMapper();
        // configure the object mapper here, eg.
           objectMapper.configure(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS, false);
        return objectMapper;
    }
}
导入javax.ws.rs.ext.ContextResolver;
导入javax.ws.rs.ext.Provider;
导入org.codehaus.jackson.map.ObjectMapper;
导入org.codehaus.jackson.map.SerializationConfig.Feature;
导入org.codehaus.jackson.map.desr.CustomDeserializerFactory;
导入org.codehaus.jackson.map.desr.StdDeserializerProvider;
导入org.codehaus.jackson.map.ser.CustomSerializerFactory;
导入org.springframework.stereotype.Component;
//告诉斯普林找这个。
@组成部分
//告诉spring它是一个提供者(类型由实现决定)
@提供者
公共类ObjectMapperProvider实现ContextResolver{
@凌驾
公共对象映射器getContext(类类型){
//创建objectMapper。
ObjectMapper ObjectMapper=新的ObjectMapper();
//在这里配置对象映射器,例如。
configure(SerializationConfig.Feature.WRITE_DATES_作为时间戳,false);
返回对象映射器;
}
}

我设法用Resteasy的“JAX-RS方式”实现了这一点,因此它应该适用于像Jersey这样的所有兼容实现(最近在JEE7服务器Wildfly 8上成功测试,它只需要对Jackson部分进行一些更改,因为它们更改了一些API)

您必须定义ContextResolver(检查生成的内容是否包含正确的内容类型):

如果您只是这样做(当然,将扩展类放在RestApplication中),那么将使用父类的映射器,也就是说,您将丢失自定义映射。为了使它正常工作,我不得不做一些对我来说似乎无用的事情:

public class MyJacksonConfigurator extends JacksonConfigurator implements ContextResolver<ObjectMapper> 
公共类MyJacksonConfigurator扩展JacksonConfigurator实现ContextResolver

使用以下命令重新编写MessageBodyWriterJSON

import javax.ws.rs.core.MediaType; 
import javax.ws.rs.ext.Provider; 

import org.codehaus.jackson.jaxrs.JacksonJsonProvider; 
import org.codehaus.jackson.map.ObjectMapper; 
import org.codehaus.jackson.map.SerializationConfig; 

@Provider 
public class MessageBodyWriterJSON extends JacksonJsonProvider { 
            public MessageBodyWriterJSON (){ 
            } 

        @Override 
            public ObjectMapper locateMapper(Class<?> type, MediaType mediaType) 
        { 
        ObjectMapper mapper = super.locateMapper(type, mediaType); 
        //DateTime in ISO format "2012-04-07T17:00:00.000+0000" instead of 'long' format 
            mapper.configure(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS, false); 
            return mapper; 
        } 
}
导入javax.ws.rs.core.MediaType;
导入javax.ws.rs.ext.Provider;
导入org.codehaus.jackson.jaxrs.JacksonJsonProvider;
导入org.codehaus.jackson.map.ObjectMapper;
导入org.codehaus.jackson.map.SerializationConfig;
@提供者
公共类MessageBodyWriterJSON扩展JacksonJsonProvider{
public MessageBodyWriterJSON(){
} 
@凌驾
公共对象映射器locateMapper(类类型,MediaType,MediaType)
{ 
ObjectMapper mapper=super.locateMapper(类型,mediaType);
//日期时间采用ISO格式“2012-04-07T17:00:00.000+0000”而不是“长”格式
configure(SerializationConfig.Feature.WRITE_DATES_为时间戳,false);
返回映射器;
} 
}

如果您选择使用服务器上的Joda DateTime对象并希望序列化为ISO8601,则可以使用。您可以按如下方式注册Jersey提供商:

import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.joda.JodaModule;

@Provider
public class MyObjectMapperProvider implements ContextResolver<ObjectMapper> {

  final ObjectMapper objectMapper;

  public MyObjectMapperProvider() {
    objectMapper = new ObjectMapper();
    /* Register JodaModule to handle Joda DateTime Objects. */
    objectMapper.registerModule(new JodaModule());
    /* We want dates to be treated as ISO8601 not timestamps. */
    objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
  }

  @Override
  public ObjectMapper getContext(Class<?> arg0) {
    return objectMapper;
  }
}
导入javax.ws.rs.ext.ContextResolver;
导入javax.ws.rs.ext.Provider;
导入com.fasterxml.jackson.databind.ObjectMapper;
导入com.fasterxml.jackson.databind.SerializationFeature;
导入com.fasterxml.jackson.datatype.joda.JodaModule;
@提供者
公共类MyObjectMapperProvider实现ContextResolver{
最终对象映射器对象映射器;
公共MyObjectMapperProvider(){
objectMapper=新的objectMapper();
/*注册JodaModule以处理Joda DateTime对象*/
registerModule(新的JodaModule());
/*我们希望日期被视为ISO8601,而不是时间戳*/
configure(SerializationFeature.WRITE_DATES_作为时间戳,false);
}
@凌驾
公共对象映射器getContext(类arg0){
返回对象映射器;
}
}
有关的更多信息。

json io()是一个完整的Java到/从json序列化库。使用它编写JSON字符串时,可以设置日期的格式。默认情况下,日期写得一样长(如上所述,从1970年1月1日起为毫秒)。但是,您可以给它一个格式字符串或Java DateFormatter,并让它以您想要的任何格式写入日期。

我也遇到了同样的问题(使用Jersey+Jackson+Json),客户机正在发送日期,但当数据映射到对象时,它在服务器中被更改

当我意识到收到的日期是一个时间戳时(与Adrin的问题相同:
“creationDate”:1292236718456
),我采用了另一种方法来解决这个问题

在我的VO类中,我将此注释添加到属性
@XmlJavaTypeAdapter
和al中
import javax.ws.rs.core.MediaType;
@Provider
@Produces(MediaType.APPLICATION_JSON)
public class MyJacksonConfigurator extends JacksonConfigurator
public class MyJacksonConfigurator extends JacksonConfigurator implements ContextResolver<ObjectMapper> 
import javax.ws.rs.core.MediaType; 
import javax.ws.rs.ext.Provider; 

import org.codehaus.jackson.jaxrs.JacksonJsonProvider; 
import org.codehaus.jackson.map.ObjectMapper; 
import org.codehaus.jackson.map.SerializationConfig; 

@Provider 
public class MessageBodyWriterJSON extends JacksonJsonProvider { 
            public MessageBodyWriterJSON (){ 
            } 

        @Override 
            public ObjectMapper locateMapper(Class<?> type, MediaType mediaType) 
        { 
        ObjectMapper mapper = super.locateMapper(type, mediaType); 
        //DateTime in ISO format "2012-04-07T17:00:00.000+0000" instead of 'long' format 
            mapper.configure(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS, false); 
            return mapper; 
        } 
}
import javax.ws.rs.ext.ContextResolver;
import javax.ws.rs.ext.Provider;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.datatype.joda.JodaModule;

@Provider
public class MyObjectMapperProvider implements ContextResolver<ObjectMapper> {

  final ObjectMapper objectMapper;

  public MyObjectMapperProvider() {
    objectMapper = new ObjectMapper();
    /* Register JodaModule to handle Joda DateTime Objects. */
    objectMapper.registerModule(new JodaModule());
    /* We want dates to be treated as ISO8601 not timestamps. */
    objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
  }

  @Override
  public ObjectMapper getContext(Class<?> arg0) {
    return objectMapper;
  }
}
@XmlRootElement
public class MyClassVO {
   ...
   @XmlJavaTypeAdapter(DateFormatterAdapter.class) 
   Date creationDate;
   ...

   private static class DateFormatterAdapter extends XmlAdapter<String, Date> {
      @Override
      public Date unmarshal(final String v) throws Exception {
         Timestamp stamp = new Timestamp(new Long(v));
         Date date = new Date(stamp.getTime());
         return date;
      }
}
import java.text.SimpleDateFormat;

import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.ext.Provider;

import org.codehaus.jackson.jaxrs.JacksonJaxbJsonProvider;
import org.codehaus.jackson.map.DeserializationConfig;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig;
import org.codehaus.jackson.map.annotate.JsonSerialize.Inclusion;


@Provider
@Produces(MediaType.APPLICATION_JSON)
public class JsonProvider extends JacksonJaxbJsonProvider {
  private static final ObjectMapper objectMapper = new ObjectMapper();
  static {
    // allow only non-null fields to be serialized
    objectMapper.getSerializationConfig().setSerializationInclusion(Inclusion.NON_NULL);

    SerializationConfig serConfig = objectMapper.getSerializationConfig();
    serConfig.setDateFormat(new SimpleDateFormat(<your date format>));
    DeserializationConfig deserializationConfig = objectMapper.getDeserializationConfig();
    deserializationConfig.setDateFormat(new SimpleDateFormat(<your date format>));
    objectMapper.configure(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS, false);

  }

  public JsonProvider() {
    super.setMapper(objectMapper);
  }
}