json - 在 Play 2.0 中从 JSON 反序列化回 joda DateTime

标签 json playframework deserialization playframework-2.0 jodatime

我想不出允许在我的应用程序中为日期时间字段发布 JSON 的魔法词。查询时,DateTime 将以自纪元以​​来的微秒形式返回。当我尝试以这种格式发布时 ({"started":"1341006642000","task":{"id":1}}),我得到“无效值:开始”。

我还尝试将 @play.data.format.Formats.DateTime(pattern="yyyy-MM-dd HH:mm:ss") 添加到 started字段并发布 {"started":"2012-07-02 09:24:45","task":{"id":1}} 具有相同的结果。

Controller 方法是:

@BodyParser.Of(play.mvc.BodyParser.Json.class)
public static Result create(Long task_id) {
    Form<Run> runForm = form(Run.class).bindFromRequest();
    for (String key : runForm.data().keySet()) {
        System.err.println(key + " => " + runForm.apply(key).value() + "\n");
    } 
    if (runForm.hasErrors())
        return badRequest(runForm.errorsAsJson());

    Run run = runForm.get();
    run.task = Task.find.byId(task_id);
    run.save();

    ObjectNode result = Json.newObject();
    result.put("id", run.id);

    return ok(result);
}

我还可以从输出中看到这些值被正确接收。有人知道如何做到这一点吗?

最佳答案

阅读 Handling form submission 的“注册自定义 DataBinder”部分后页面以及 Application global settings页面并与 this question 进行比较我想出了以下解决方案:

我创建了一个带有可选格式属性的自定义注释:

package models;

import java.lang.annotation.*;

@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
@play.data.Form.Display(name = "format.joda.datetime", attributes = { "format" })
public @interface JodaDateTime {
    String format() default "";
}

并从onStart注册了一个自定义格式化程序:

import java.text.ParseException;
import java.util.Locale;

import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;

import play.*;
import play.data.format.Formatters;


public class Global extends GlobalSettings {

    @Override
    public void onStart(Application app) {
        Formatters.register(DateTime.class, new Formatters.AnnotationFormatter<models.JodaDateTime,DateTime>() {
                @Override
                public DateTime parse(models.JodaDateTime annotation, String input, Locale locale) throws ParseException {
                    if (input == null || input.trim().isEmpty())
                        return null;

                    if (annotation.format().isEmpty())
                        return new DateTime(Long.parseLong(input));
                    else
                        return DateTimeFormat.forPattern(annotation.format()).withLocale(locale).parseDateTime(input);
                }

                @Override
                public String print(models.JodaDateTime annotation, DateTime time, Locale locale) {
                    if (time == null)
                        return null;

                    if (annotation.format().isEmpty())
                        return time.getMillis() + "";
                    else
                        return time.toString(annotation.format(), locale);
                }

        });
    }

}

如果需要,您可以指定格式,否则默认情况下将使用自纪元以来的毫秒数。我希望有一种更简单的方法,因为 Joda 包含在 Play 发行版中,但这让事情正常了。

注意:您需要重新启动 Play 应用,因为它似乎没有检测到 Global 类的更改。

关于json - 在 Play 2.0 中从 JSON 反序列化回 joda DateTime,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11295776/

相关文章:

javascript - 如何从 WebAPI Controller 使用 javascript 函数发送 JSON(不带引号)

c# - 使用 XmlReader 和 xsd.exe 中的类反序列化 Xml

java - 使用 Jackson XmlMapper 将 XML 反序列化为 POJO

json - 将 golang map[string] 接口(interface)存储到数据存储中的最佳方式

json - 不处理从这里抛出的 Swift 错误

sql - 使用 Postgres,如果为 NULL,我如何使用 UPDATE 插入新的 jsonb 值,或者如果值已经存在,如何修改 json?

JSON-LD 缺少 '}' 或对象成员名称。错误

java - Ebean 在启动时创建对象?

java - play2 Java EBean ORM : Inheritance and Generics

java - 无法连接到数据库 - PlayFramework + Ebean