【问题标题】:Json <-> Java serialization that works with GWT [closed]与 GWT 一起使用的 Json <-> Java 序列化 [关闭]
【发布时间】:2010-10-15 13:12:15
【问题描述】:

我正在寻找一个simple Json (de)serializer for Java,它可能适用于 GWT。我用谷歌搜索了一下,发现一些解决方案要么需要注释每个成员,要么定义无用的接口。挺无聊的。为什么我们没有一些非常简单的东西,比如

class MyBean {
    ...
}

new GoodSerializer().makeString(new MyBean());
new GoodSerializer().makeObject("{ ... }", MyBean.class)

【问题讨论】:

标签: json serialization gwt marshalling javabeans


【解决方案1】:

看看 GWT 的Overlay Types。我认为这是迄今为止在 GWT 中使用 JSON 最简单的方法。这是链接文章中修改后的代码示例:

public class Customer extends JavaScriptObject {
    public final native String getFirstName() /*-{ 
        return this.first_name;
    }-*/;
    public final native void setFirstName(String value) /*-{
        this.first_name = value;
    }-*/;
    public final native String getLastName() /*-{
        return this.last_name;
    }-*/;
    public final native void setLastName(String value) /*-{
        this.last_name = value;
    }-*/;
}

一旦定义了覆盖类型,就很容易从 JSON 创建一个 JavaScript 对象并在 Java 中访问它的属性:

public static final native Customer buildCustomer(String json) /*-{
    return eval('(' + json + ')');
}-*/;

如果你想要对象的 JSON 表示,你可以将覆盖类型包装在一个 JSONObject 中:

Customer customer = buildCustomer("{'Bart', 'Simpson'}");
customer.setFirstName("Lisa");
// Displays {"first_name":"Lisa","last_name":"Simpson"}
Window.alert(new JSONObject(customer).toString());

【讨论】:

  • 我对覆盖类型的主要问题是它们意味着您不能在 java 端使用与 GWT 端相同的对象表示。但是我还没有找到更好的反序列化解决方案。
  • 我相信最好的办法是注释 getter 并在编译时生成(反)序列化方法
  • 为什么不直接使用 GWT 的内置 JSON 库呢? google-web-toolkit.googlecode.com/svn/javadoc/2.0/com/google/… 或者在提出这个问题时还没有这个?我将在下面添加并回答。
  • @mooreds 你可以。您可以让您的 GWT JSO 实现一个接口,但它必须是唯一的类型来取消此接口,并且您必须使用 @SingleJsoImpl 注释此接口。然后,您可以在服务器端重用该接口。
【解决方案2】:

要尝试的另一件事是 GWT 2.1 引入的新 AutoBean 框架。

您为您的 bean 定义接口和出售它们的工厂,然后 GWT 为您生成实现。

interface MyBean {
  String getFoo();
  void setFoo(String foo);
}

interface MyBiggerBean {
  List<MyBean> getBeans();
  void setBeans(List<MyBean> beans>;
}

interface Beanery extends AutoBeanFactory{
  AutoBean<MyBean> makeBean();
  AutoBean<MyBiggerBean> makeBigBean();
}

Beanery beanFactory = GWT.create(Beanery.class);

void go() {
  MyBean bean = beanFactory.makeBean().as();
  bean.setFoo("Hello, beans");
}

AutoBeanCodex 可用于将它们与 json 序列化。

AutoBean<MyBean> autoBean = AutoBeanUtils.getAutoBean(bean);
String asJson = AutoBeanCodex.encode(autoBean).getPayload();

AutoBean<MyBean> autoBeanCloneAB = 
  AutoBeanCodex.decode(beanFactory, MyBean.class, asJson );

MyBean autoBeanClone = autoBeanCloneAB.as(); 
assertTrue(AutoBeanUtils.deepEquals(autoBean, autoBeanClone));

它们也在服务器端工作——使用AutoBeanFactoryMagic.create(Beanery.class) 而不是GWT.create(Beanery.class)

【讨论】:

  • 如果您在服务器端拥有 DTO,并且您想重用您的接口,那么 AutoBean 绝对是您的最佳选择。谢谢 rjrjr,它救了我的命……(或至少几个小时)
  • 这需要在非 gwt 服务器上使用接口和 pojos。有纯 Jackson 兼容的 pojo 解决方案吗?
  • 您可以在 GWT 客户端中使用 AutoBean 并使用您喜欢的框架创建 JSON。它是网络上的纯 JSON。
  • 如果我可以多次投票,我会的。解决难题的绝妙方法。
【解决方案3】:

最简单的方法是使用 GWT 的内置 JSON API。这是the documentation。这里有一个great tutorial关于如何使用它。

就这么简单:

String json = //json string
JSONValue value = JSONParser.parse(json);

JSONValue API 非常酷。它允许您在从 JSON 对象中提取值时链接验证,以便在格式有任何问题时抛出异常。

【讨论】:

  • 更不用说,效率更高。
【解决方案4】:

看来我找到了问题的正确答案

我发现 GWT 中的 bean 到 json 和 json 到 bean 的转换并不是一项简单的任务。已知库将无法工作,因为 GWT 需要它们的完整源代码,并且该源代码必须仅使用 GWT 模拟的 Java 类。此外,您不能在 GWT 中使用反射。非常苛刻的要求!

我找到了唯一一个名为 gwt-jsonizer 的现有解决方案。它使用一个自定义的Generator 类,并且每个“jsonable”bean 都需要一个附属接口。可惜不打最新版的GWT就不行了,好久没更新了。

所以,我个人认为让我的 bean 知道如何将自己与 json 相互转换更便宜、更快捷。像这样:

public class SmartBean {
    private String name;

    public String getName() { return name; }
    public void setName(String value) { name = value;  }

    public JSONObject toJson() {
        JSONObject result = new JSONObject();
        result.put("name", new JSONString(this.name));
        return result;
    }
    public void fromJson(JSONObject value) {
        this.name = value.get("name").isString().stringValue();
    }

}

JSONxxxx 是提供低级 json 支持的 GWT 内置类。

【讨论】:

  • 有趣。对我来说,这似乎是 GWT 的一个缺点。但很高兴知道有办法。我将来可能需要自己做这件事,因为我们有一个使用 GWT 编写的仪表板应用程序。
  • 是的,这就是他们最终开发内置 GWT JSON 解析器的原因。 google-web-toolkit.googlecode.com/svn/javadoc/2.0/com/google/…我也添加了更完整的答案。
  • 这应该被标记为答案,因为它是最干净的方式,并且不依赖任何非核心 GWT 库来完成。
【解决方案5】:

RestyGWT 是一个强大的库,用于在 GWT 中将 Java 对象编码或解码为 JSON:

import javax.ws.rs.POST;
...
public interface PizzaOrderCodec extends JsonEncoderDecoder<PizzaOrder> {
}

然后:

// GWT will implement the interface for you
PizzaOrderCodec codec = GWT.create(PizzaOrderCodec.class);

// Encoding an object to json
PizzaOrder order = ... 
JSONValue json = codec.encode(order);

// decoding an object to from json
PizzaOrder other = codec.decode(json);

它还有几个易于使用的 API 用于使用 Restful 网络服务。

玩得开心。

【讨论】:

    【解决方案6】:

    检查一下:

    GWT 专业 JSON 序列化器: http://code.google.com/p/gwtprojsonserializer/

    !适用于 GWT 2.0+!

    【讨论】:

    【解决方案7】:

    json.org/java 这些天似乎包含在 GWT 中:

    gwt-servlet-deps.jar\org\json\

    或者,这个项目似乎很全面: http://code.google.com/p/piriti/

    【讨论】:

    • 我认为现在(截至本评论日期)Piriti 和 RestyGWT 是两个最佳解决方案。 RestyGWT 的侵入性远低于 Piriti,但 Piriti 似乎更强大。
    【解决方案8】:

    在 Google Web Toolkit Applications 第 510 至 522 页中,作者 Ryan Dewsbury 展示了如何使用 GWT 代码生成对 XML 和 JSON 文档进行序列化。

    你可以download the code here;您想要第 10 章的代码包,然后您想要查看 src/com/gwtapps/serialization 包。我没有看到此代码的许可证,但已通过电子邮件发送给作者以查看他所说的内容。如果他回复我会更新这个。

    此解决方案的问题:

    • 你必须在你想要序列化的所有对象上添加一个标记接口(他使用 java.io.Serializable,但我想你可以使用其他对象——如果你使用 hibernate 作为后端,你的 pojo 可能已经被标记了像这样)。
    • 代码只支持字符串属性;可以延长。
    • 代码仅针对 1.4 和 1.5 编写。

    因此,这不是一个开箱即用的解决方案,而是构建适合 GWT 的 JSON 序列化程序的一个很好的起点。将它与服务器端的 JSON 序列化程序结合起来,例如 json-lib,您就可以开始了。

    我还找到了this project(同样,需要一些标记接口)。

    【讨论】:

      【解决方案9】:

      从 Google 代码尝试这个序列化程序:http://code.google.com/p/json-io/

      如果您需要在 Java 中编写或读取 JSON 格式,这是可以使用的工具。无需创建额外的类等。一次调用即可将 Java 对象图转换为 JSON 格式。做相反的事情 - 创建一个 JSON 字符串或流到 Java 对象。这是我见过的最快的库。在大多数情况下,它比使用二进制格式的 ObjectOutputStream 和 ObjectInputStream 快。

      非常方便的实用程序。

      【讨论】:

        【解决方案10】:

        你可能想签出这个项目https://gerrit.googlesource.com/gwtjsonrpc/

        它是一个为支持 Android 代码审查系统 Gerrit 而创建的库,但它是一个独立模块,旨在嵌入到任何 GWT 项目中,而不仅仅是 Gerrit。

        一个合理的教程可能是目录顶层的README。它与标准 GWT RPC 非常相似,但它使用 JSON 编码。它还具有内置的 XSRF 保护。

        【讨论】:

          【解决方案11】:

          我似乎经常回答这个问题......

          code.google.com 上有一个名为 Using GWT for JSON Mashups 的页面。 (不幸的是)这超出了我的想象,因为我对 GWT 不太熟悉,所以它可能没有帮助。

          【讨论】:

            【解决方案12】:

            好的,我删除了我之前的答案,因为结果证明这正是你不想要的。

            我不知道它与 GWT 的工作情况如何,但我们使用 json-lib 库在我工作的普通 Java 项目中序列化对象。

            它可以create a JSONObject directly from a JavaBean,然后使用生成的 JSONObject 的 toString() 方法来获取实际的 JSON 字符串。

            同样,它也可以转JSON back into a JavaBean

            【讨论】:

            • 依赖 Java 反射的 JSON 编组器无法与 GWT 一起使用
            【解决方案13】:

            不确定Jackson 是否适合您。 我不知道您是否正在寻找特定于 GWT 的产品;如果没有,它应该可以工作。

            但是它的序列化/反序列化效果很好,比如:

            // read json, create object
            ObjectMapper mapper = new ObjectMapper();
            MyBean bean = mapper.readValue(jsonAsString, MyBean.class);
            
            // and write out
            StringWriter sw = new StringWriter();
            mapper.writeValue(sw, user);
            String jsonOut = sw.toString();
            

            您确实需要访问器(getX() 用于序列化,setX() 用于反序列化;可以用其他名称注释方法),仅此而已。

            【讨论】:

            • Jackson 是一个很棒的工具,但它不能被 GWT 交叉编译成 JavaScript,因为对象映射器可能大量使用反射——GWT 领域不支持的 Java 特性.
            • 啊。是的,有道理,感谢您指出这一点(给定 js-to-java 转换)
            • gwt-jackson "是一种基于Jackson注解的GWT JSON序列化/反序列化机制"
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2014-08-19
            • 2012-11-01
            • 1970-01-01
            • 2021-12-27
            • 1970-01-01
            • 2013-10-22
            相关资源
            最近更新 更多