序列化映射<日期 ,字符串>与杰克逊

发布于 2024-11-18 13:21:34 字数 399 浏览 2 评论 0原文

我想连载杰克逊的地图。 日期应该被序列化为时间戳,就像我的所有其他日期一样。

以下代码以“Tue Mar 11 00:00:00 CET 1952”(即 Date.toString())形式呈现键,而不是时间戳。

Map<Date, String> myMap = new HashMap<Date, String>();
...
ObjectMapper.writeValue(myMap)

我认为这是因为类型擦除,并且杰克逊在运行时不知道该键是日期。但我没有找到将 TypeReference 传递给任何 writeValue 方法的方法。

有没有一种简单的方法来实现我想要的行为,或者所有的键总是由杰克逊呈现为字符串?

感谢您的任何提示。

I want to serialize a Map with Jackson.
The Date should be serialized as a timestamp, like all my other dates.

The following code renders the keys in the form "Tue Mar 11 00:00:00 CET 1952" (which is Date.toString()) instead of the timestamp.

Map<Date, String> myMap = new HashMap<Date, String>();
...
ObjectMapper.writeValue(myMap)

I assume this is because of type erasure and jackson doesn't know at runtime that the key is a Date. But I didn't find a way to pass a TypeReference to any writeValue method.

Is there a simple way to achieve my desired behaviour or are all keys always rendered as Strings by jackson?

Thanks for any hint.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

岁月苍老的讽刺 2024-11-25 13:21:34

默认的映射键序列化器是 StdKeySerializer,它只是执行此操作。

String keyStr = (value.getClass() == String.class) ? ((String) value) : value.toString();
jgen.writeFieldName(keyStr);

您可以使用 SimpleModule功能,并使用 addKeySerializer 方法指定自定义密钥序列化程序。


下面是如何做到这一点。

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.Version;
import org.codehaus.jackson.map.JsonSerializer;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.ObjectWriter;
import org.codehaus.jackson.map.SerializerProvider;
import org.codehaus.jackson.map.module.SimpleModule;
import org.codehaus.jackson.map.type.MapType;
import org.codehaus.jackson.map.type.TypeFactory;

public class CustomKeySerializerDemo
{
  public static void main(String[] args) throws Exception
  {
    Map<Date, String> myMap = new HashMap<Date, String>();
    myMap.put(new Date(), "now");
    Thread.sleep(100);
    myMap.put(new Date(), "later");

    ObjectMapper mapper = new ObjectMapper();
    System.out.println(mapper.writeValueAsString(myMap));
    // {"Mon Jul 04 11:38:36 MST 2011":"now","Mon Jul 04 11:38:36 MST 2011":"later"}

    SimpleModule module =  
      new SimpleModule("MyMapKeySerializerModule",  
          new Version(1, 0, 0, null));
    module.addKeySerializer(Date.class, new DateAsTimestampSerializer());

    MapType myMapType = TypeFactory.defaultInstance().constructMapType(HashMap.class, Date.class, String.class);

    ObjectWriter writer = new ObjectMapper().withModule(module).typedWriter(myMapType);
    System.out.println(writer.writeValueAsString(myMap));
    // {"1309806289240":"later","1309806289140":"now"}
  }
}

class DateAsTimestampSerializer extends JsonSerializer<Date>
{
  @Override
  public void serialize(Date value, JsonGenerator jgen, SerializerProvider provider) 
      throws IOException, JsonProcessingException
  {
    jgen.writeFieldName(String.valueOf(value.getTime()));
  }
}

最新 Jackson (2.0.4) 的更新:

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.type.MapType;
import com.fasterxml.jackson.databind.type.TypeFactory;

public class CustomKeySerializerDemo
{
  public static void main(String[] args) throws Exception
  {
    Map<Date, String> myMap = new HashMap<Date, String>();
    myMap.put(new Date(), "now");
    Thread.sleep(100);
    myMap.put(new Date(), "later");

    ObjectMapper mapper = new ObjectMapper();
    System.out.println(mapper.writeValueAsString(myMap));
    // {"2012-07-13T21:14:09.499+0000":"now","2012-07-13T21:14:09.599+0000":"later"}

    SimpleModule module = new SimpleModule();
    module.addKeySerializer(Date.class, new DateAsTimestampSerializer());

    MapType myMapType = TypeFactory.defaultInstance().constructMapType(HashMap.class, Date.class, String.class);

    ObjectWriter writer = new ObjectMapper().registerModule(module).writerWithType(myMapType);
    System.out.println(writer.writeValueAsString(myMap));
    // {"1342214049499":"now","1342214049599":"later"}
  }
}

class DateAsTimestampSerializer extends JsonSerializer<Date>
{
  @Override
  public void serialize(Date value, JsonGenerator jgen, SerializerProvider provider) 
      throws IOException, JsonProcessingException
  {
    jgen.writeFieldName(String.valueOf(value.getTime()));
  }
}

The default map key serializer is StdKeySerializer, and it simply does this.

String keyStr = (value.getClass() == String.class) ? ((String) value) : value.toString();
jgen.writeFieldName(keyStr);

You could make use of the SimpleModule feature, and specify a custom key serializer, using the addKeySerializer method.


And here's how that could be done.

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import org.codehaus.jackson.JsonGenerator;
import org.codehaus.jackson.JsonProcessingException;
import org.codehaus.jackson.Version;
import org.codehaus.jackson.map.JsonSerializer;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.ObjectWriter;
import org.codehaus.jackson.map.SerializerProvider;
import org.codehaus.jackson.map.module.SimpleModule;
import org.codehaus.jackson.map.type.MapType;
import org.codehaus.jackson.map.type.TypeFactory;

public class CustomKeySerializerDemo
{
  public static void main(String[] args) throws Exception
  {
    Map<Date, String> myMap = new HashMap<Date, String>();
    myMap.put(new Date(), "now");
    Thread.sleep(100);
    myMap.put(new Date(), "later");

    ObjectMapper mapper = new ObjectMapper();
    System.out.println(mapper.writeValueAsString(myMap));
    // {"Mon Jul 04 11:38:36 MST 2011":"now","Mon Jul 04 11:38:36 MST 2011":"later"}

    SimpleModule module =  
      new SimpleModule("MyMapKeySerializerModule",  
          new Version(1, 0, 0, null));
    module.addKeySerializer(Date.class, new DateAsTimestampSerializer());

    MapType myMapType = TypeFactory.defaultInstance().constructMapType(HashMap.class, Date.class, String.class);

    ObjectWriter writer = new ObjectMapper().withModule(module).typedWriter(myMapType);
    System.out.println(writer.writeValueAsString(myMap));
    // {"1309806289240":"later","1309806289140":"now"}
  }
}

class DateAsTimestampSerializer extends JsonSerializer<Date>
{
  @Override
  public void serialize(Date value, JsonGenerator jgen, SerializerProvider provider) 
      throws IOException, JsonProcessingException
  {
    jgen.writeFieldName(String.valueOf(value.getTime()));
  }
}

Update for the latest Jackson (2.0.4):

import java.io.IOException;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.type.MapType;
import com.fasterxml.jackson.databind.type.TypeFactory;

public class CustomKeySerializerDemo
{
  public static void main(String[] args) throws Exception
  {
    Map<Date, String> myMap = new HashMap<Date, String>();
    myMap.put(new Date(), "now");
    Thread.sleep(100);
    myMap.put(new Date(), "later");

    ObjectMapper mapper = new ObjectMapper();
    System.out.println(mapper.writeValueAsString(myMap));
    // {"2012-07-13T21:14:09.499+0000":"now","2012-07-13T21:14:09.599+0000":"later"}

    SimpleModule module = new SimpleModule();
    module.addKeySerializer(Date.class, new DateAsTimestampSerializer());

    MapType myMapType = TypeFactory.defaultInstance().constructMapType(HashMap.class, Date.class, String.class);

    ObjectWriter writer = new ObjectMapper().registerModule(module).writerWithType(myMapType);
    System.out.println(writer.writeValueAsString(myMap));
    // {"1342214049499":"now","1342214049599":"later"}
  }
}

class DateAsTimestampSerializer extends JsonSerializer<Date>
{
  @Override
  public void serialize(Date value, JsonGenerator jgen, SerializerProvider provider) 
      throws IOException, JsonProcessingException
  {
    jgen.writeFieldName(String.valueOf(value.getTime()));
  }
}
有木有妳兜一样 2024-11-25 13:21:34

和往常一样,布鲁斯的回答很当场。

另一个想法是,由于存在将 Date 值序列化为时间戳的全局设置:

SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS

也许这也应该适用于这里。和/或至少使用标准 ISO-8601 文本格式。主要的实际问题是向后兼容性;但是,我怀疑当前使用的普通 toString() 是否非常有用,因为它既不高效也不方便(读回值)。

因此,如果您愿意,您可能需要提交功能请求;这听起来像是杰克逊对地图键的次优处理。

As usual, Bruce's answer is right on the spot.

One additional thought is that since there is a global setting for serializing Date values as timestamps:

SerializationConfig.Feature.WRITE_DATES_AS_TIMESTAMPS

Maybe that should apply here as well. And/or at least use standard ISO-8601 format for text. The main practical issue there is that of backwards compatibility; however, I doubt that current use of plain toString() is very useful as it is neither efficient nor convenient (to read back the value).

So if you want, you might want to file a feature request; this sounds like sub-optimal handling of Map keys by Jackson.

行雁书 2024-11-25 13:21:34

从 Jackson 2.0(也可能是 1.9)开始,可以使用 WRITE_DATE_KEYS_AS_TIMESTAMPS 来更改此特定行为。

的使用示例:

ObjectMapper m = new ObjectMapper().configure(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS, true);

ObjectMapperObjectWriter

ObjectWriter w = mapper.with(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS);

Since Jackson 2.0 (maybe 1.9, too), WRITE_DATE_KEYS_AS_TIMESTAMPS can be used to change this particular behavior.

Usage example for ObjectMapper:

ObjectMapper m = new ObjectMapper().configure(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS, true);

and for ObjectWriter:

ObjectWriter w = mapper.with(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文