41

Jersey + Jackson を使用して、アプリケーションに REST JSON サービス レイヤーを提供しています。私が抱えている問題は、デフォルトの日付シリアル化形式が次のようになっていることです。

"CreationDate":1292236718456

最初は UNIX のタイムスタンプだと思っていましたが、長すぎます。私のクライアント側の JS ライブラリには、この形式を逆シリアル化する際に問題があります (さまざまな日付形式をサポートしていますが、これはサポートしていません)。ライブラリで使用できるようにフォーマットを変更したい(たとえば、ISOに)。どうすれば...私は助けることができるコードを見つけましたが...私はJacksonのシリアライザーのインスタンス化を制御していないので、どこに置くべきですか?

objectMapper.configure(
    SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS, false);

カスタム用のこのコードも見つけました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;
        }
    }
}
4

8 に答える 8

35

私はResteasyで「JAX-RSの方法」でそれを行うことができたので、Jerseyのようなすべての準拠実装で動作するはずです(最近、JEE7サーバーWildfly 8で正常にテストされました。 API)。

ContextResolver を定義する必要があります (プロデュースに正しいコンテンツ タイプが含まれていることを確認してください)。

import javax.ws.rs.ext.ContextResolver;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.SerializationConfig;
import org.codehaus.jackson.map.DeserializationConfig;
import javax.ws.rs.ext.Provider;
import javax.ws.rs.Produces; 
import java.text.SimpleDateFormat;
@Provider
@Produces("application/json")
public class JacksonConfigurator implements ContextResolver<ObjectMapper> {

    private ObjectMapper mapper = new ObjectMapper();

    public JacksonConfigurator() {
        SerializationConfig serConfig = mapper.getSerializationConfig();
        serConfig.setDateFormat(new SimpleDateFormat(<my format>));
        DeserializationConfig deserializationConfig = mapper.getDeserializationConfig();
        deserializationConfig.setDateFormat(new SimpleDateFormat(<my format>));
        mapper.configure(SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS, false);
    }

    @Override
    public ObjectMapper getContext(Class<?> arg0) {
        return mapper;
    }

}

次に、javax.ws.rs.core.Application の getClasses で新しく作成されたクラスを返す必要があります。

import javax.ws.rs.core.Application;
public class RestApplication extends Application {

     @Override
     public Set<Class<?>> getClasses() {
         Set<Class<?>> classes = new HashSet<Class<?>>();
         // your classes here
         classes.add(JacksonConfigurator.class);
         return classes;
      }

}

このようにして、jackson を介して行われるすべての操作に、選択した ObjectMapper が与えられます。

編集: 最近、RestEasy 2.0.1 (および Jackson 1.5.3) を使用して、JacksonConfigurator を拡張してカスタム マッピングを追加すると、奇妙な動作が発生することがわかりました。

import javax.ws.rs.core.MediaType;
@Provider
@Produces(MediaType.APPLICATION_JSON)
public class MyJacksonConfigurator extends JacksonConfigurator

このようにすると (そしてもちろん拡張クラスを RestApplication に配置すると)、親クラスのマッパーが使用されます。つまり、カスタム マッピングが失われます。それを正しく機能させるには、そうでなければ役に立たないように思われることをしなければなりませんでした:

public class MyJacksonConfigurator extends JacksonConfigurator implements ContextResolver<ObjectMapper> 
于 2011-03-08T15:40:36.867 に答える
16

独自の ObjectMapper を構成するには、ContextResolver<ObjectMapper> を実装する独自のクラスを注入する必要があります。

ジャージを手に入れる正確な方法は、IOC (スプリング、ガイダンス) によって異なります。私は春を使用しており、私のクラスは次のようになります。

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;
    }
}
于 2011-01-29T06:20:27.303 に答える
6

価値があるのは、その数値が標準の Java タイムスタンプ (JDK クラスで使用される) であるということです。Unix は秒、Java ミリ秒を格納するため、値が少し大きくなります。

ObjectMapper を Jersey に注入する方法に関するドキュメントがいくつかあることを願っています (提供されたオブジェクトを注入する通常の方法に従う必要があります)。ただし、JacksonJaxRsProvider をオーバーライドして ObjectMapper を指定/構成し、それを登録することもできます。これは Jersey 自体が行うことであり、複数の方法があります。

于 2010-12-13T17:31:43.993 に答える
1

クライアントは日付を送信していましたが、データがオブジェクトにマップされたときにサーバーで変更されていました。

このリンクを読んで、これを解決するための他のアプローチに従いました: http://blog.bdoughan.com/2010/07/xmladapter-jaxbs-secret-weapon.html、受け取った日付がタイムスタンプであることに気付いたとき(同じ彼の質問のアドリンとして: "creationDate":1292236718456)

私の VO クラスでは、この注釈を属性に追加し、@XmlJavaTypeAdapter拡張された内部クラスも実装しましたXmlAdapter

@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;
      }
}

それがあなたにも役立つことを願っています。

于 2014-08-29T07:28:33.223 に答える
1

以下のコードは私のために働いた - JAX-RS 1.1、Jersy 1.8

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);
  }
}
于 2018-06-29T11:03:17.880 に答える
-1

これで 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; 
        } 
}
于 2012-04-05T14:15:54.237 に答える