当前位置: 首页 > 知识库问答 >
问题:

从不调用日期的自定义gson反序列化器

牛枫
2023-03-14

据我所知,gson不会自动将java.util.Date对象序列化和反序列化为ISO字符串,比如“yyyy-mm-ddthh:mm:ssz”或“2014-04-15t18:22:00-05:00”。因此,为了让我在客户机(使用gson改型)和服务器之间正确地通信日期,我需要指定gson的日期格式。以下是我所做的:

// code defining the creation of a RestAdapter
// ...
new GsonBuilder()
    .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
    .create()

添加。SetDateFormat行就足以让gson正确地将时间戳字符串反序列化为日期对象。但是,它没有将日期对象序列化为时间戳字符串。因此,我假设必须创建一个自定义序列化程序,如下所示:

// code defining the creation of a RestAdapter
// ...
new GsonBuilder()
    .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
    .registerTypeAdapter(Date.class, new DateSerializer())
    .create()

和DateSerializer类:

class DateSerializer implements JsonSerializer<Date> {
    @Override
    public JsonElement serialize(Date arg0, Type arg1, JsonSerializationContext arg2) {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.US);
        return new JsonPrimitive(df.format(arg0));
    }
}
public JsonElement serialize(Date arg0, Type arg1, JsonSerializationContext arg2) {
    throw new RuntimeException("Serialize function called!");
}

有人知道为什么我的serialize函数被忽略吗?我想我在某个地方读到过,对于某些类型,如果为超类定义了registerTypeAdapter,则会忽略registerTypeAdapter,但由于这是java.util.Date,如果这是问题所在,我会感到困惑。我可能只是在做一些愚蠢的事情,但我可能不知道日期或gson足够好来意识到这一点。

Edit:围绕下面的代码提供了更多上下文:

myapplication.java

public class MyApplication extends Application {
    public static RestAdapter restAdapter;
    public static The1Api the1Api;

    public static void createRestAdapter(String server_url){
        // enable cookies
        CookieManager cookieManager = new CookieManager();
        cookieManager.setCookiePolicy(CookiePolicy.ACCEPT_ALL);
        CookieHandler.setDefault(cookieManager);

        // create rest adapter
        restAdapter = new RestAdapter.Builder()
            .setEndpoint(server_url)
            .setConverter(new GsonConverter(new GsonBuilder()
                    .setDateFormat("yyyy-MM-dd'T'HH:mm:ssZ")
                    .registerTypeAdapter(Date.class, new DateSerializer())
                    .create()))
            .setLogLevel(LogLevel.FULL)
            .setLog(new ResponseInterceptor())
            .build();

        // create API
        the1Api = restAdapter.create(The1Api.class);
    }
}
public interface The1Api {
    /* Chat */

    public class PublicMessage {
        String from_user;
        String message;
        Date time;
        Integer microsecond;
        Boolean in_1_percent;
    }
    public class PublicMessageList {
        Integer last_message_id;
        ArrayList<PublicMessage> messages;
    }

    @GET("/chat/get_public_messages/")
    public PublicMessageList getPublicMessages(
            @Query("last_message_id") Integer last_message_id, // optional
            @Query("since") Date since, // optional
            @Query("max") Integer max // optional
            );   

    // ...
}
public class LoginActivity extends Activity {
    // ...

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Crashlytics.start(this);
        MyApplication.createRestAdapter(getString(R.string.server_url));
        setContentView(R.layout.activity_login);
    }

    @Override
    protected void onPostCreate(Bundle savedInstanceState){
        super.onPostCreate(savedInstanceState);

        Thread thread = new Thread(){
            @Override
            public void run(){
                ArrayList<The1Api.PublicMessage> publicMessages = MyApplication.the1Api.getPublicMessages(null, null, null).messages;
                for (The1Api.PublicMessage m : publicMessages){
                    Log.d("The1", "[" + m.time.toString() + "] " + m.from_user + ": " + m.message);
                }
                // when the following line gets executed, my server receives a request including the date below,
                // but the server does not understand the format of the date because it does not get serialized properly
                MyApplication.the1Api.getPublicMessages(null, new Date(1000000000), null);
            }
        };
        thread.start();
    }

    // ...    
}
class DateSerializer implements JsonSerializer<Date> {
    @Override
    public JsonElement serialize(Date arg0, Type arg1, JsonSerializationContext arg2) {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ", Locale.US);
        return new JsonPrimitive(df.format(arg0));
    }
}

编辑2:目前还没有解决方案,但作为一种解决办法,你可以在发送日期之前手动转换成其他格式。在Kalel建议将其转换为字符串的注释中,我将其转换为Long(UNIX时代以来的秒数)。

共有1个答案

马寒
2023-03-14

gson中的问题是,当我们尝试用after调用setdateformat反序列化时,自定义datedesializer不调用。

因此,当反序列化时,不要调用setdateformat;)

 类似资料:
  • 我有一个JestClient(elasticsearch)响应,我试图将其反序列化为一个对象。该对象包含两个DateTime字段,而在响应中,它们是字符串,因此我得到: 所以,我创建了一个自定义反序列化器来解决这个问题…然而,无论我做什么,我总是得到同样的错误。不知何故它没有注册使用它? 最后,我试图解析JestClient响应的代码: 无论我尝试什么,我总是得到上面的错误,我甚至不确定在这一点上

  • 问题内容: 我在使用Gson解析JSON响应时遇到问题。 JSON字串: 我有这两个课程: 但是当使用Gson解析这个时我有一个异常。我知道这是因为响应数组的第一个元素不是对象,而是整数。 所以问题是,我能以某种方式解决它吗? 问题答案: 您必须编写一个 自定义反序列化器 。我会做这样的事情: 首先,您需要包括一个新的类,而不是已有的两个类: 然后,您需要一个自定义解串器,类似于以下内容: 然后,

  • 问题内容: 确定,所以我编辑了问题,因为它不够清楚。 编辑2 :更新了JSON文件。 我在Android应用程序中使用GSON,我需要解析来自服务器的JSON文件,这些文件有点太复杂了。我不想让我的对象结构太沉重,所以我想简化内容: 所以我的对象的结构将不是JSON文件的结构。 例如,如果在JSON中,我有以下内容: 我不想保留我当前的对象结构,即一个对象,其中包含一个和一个“总计”。但是我只想将

  • 我有一个不能用Gson正确序列化的类(类只是name和HashMap),所以我编写了一个自定义序列化程序来从HashMap中打印名称和键值对。 此外,这是实际打印的内容,序列化整个对象并不像我所期望的那样工作,也不只是直接打印对象。 任何帮助都将不胜感激。

  • 我想反序列化表单中的类: 其中文本是加密的,反序列化应该在重建TestFieldEncryptedMessage实例之前取消对值的加密。 我采用的方法非常类似于:https://github.com/codesqueak/jackson-json-crypto 也就是说,我正在构建一个扩展SimpleModule的模块: 如您所见,设置了两个修饰符:EncryptedSerializerModif

  • 奇怪的是下面的测试用例会失败。有人知道为什么吗?