【问题标题】:How to deserialize this JSON in an elegant way using flexjson如何使用 flexjson 以一种优雅的方式反序列化这个 JSON
【发布时间】:2014-02-18 19:28:48
【问题描述】:

我正在使用 Oracle OPAM,它有一个具有类似方法的 REST API

{
   "Target Collection":[
      {
     "target":{
        "uri":"https:\/\/opam_server_host:opam_ssl_port\/opam\/target\

           /9bbcbbb087174ad1900ea691a2573b61",
        "type":"ldap",
        "name":"person1-ldap",
        "host":"opam_server_host",
        "domain":"berkeley"
        "description" : "Ldap target"
     }
      },
      {
     "target":{
        "uri":"https:\/\/opam_server_host:opam_ssl_port\/opam\/target\

           /ac246a162ce948c7b1cdcc17dfc92c15",
        "type":"ldap",
        "name":"person1-ldap2",
        "host":"opam_server_host:opam_ssl_port",
        "domain":"berkeley"
        "description" : "Ldap target"
     }
      }
   ]
}

我正在使用 FlexJSON 反序列化这些实体。如果可以的话,我会使用 Apache CXF 为我生成 bean,但问题是 WADL 处于无效的 https 证书 + 基本身份验证下,并且让 wadl2java 在这些条件下工作需要比我更多的时间喜欢花钱(可惜它不是 WSDL,所以我可以从 eclipse 内部快速轻松地创建存根)。

所以我使用这种繁琐的方法和 flexjson 来解析这个 REST API

JSONDeserializer<Map<String,List<Map<String,Map<String,String>>>>> json = new JSONDeserializer<>();
Map<String,List<Map<String,Map<String,String>>>> targetCollection = json.deserialize(new InputStreamReader(content));
List<Map<String,Map<String,String>>> col = targetCollection.get("Target Collection");             Map<String,Map<String,String>> keyVal = col.get(0);
Map<String,String> targetVal = keyVal.get("target");
System.out.println(targetVal);

这显然有效,但它有很多括号让我想起 LISP。

如果我们可以只使用 POJO 会更好(如果我可以通过一些 GUI 工具自动生成,那就更好了,但我知道我要求太多了,我们生活在 2014 年)。

我知道这里有一些关于如何映射属性的文档:http://flexjson.sourceforge.net/#Deserialization 但我真的希望他们有一些真正复杂的示例(包括 JSON - 在文档中解释如何在没有任何 JSON 示例的情况下进行反序列化有什么用? )

这个问题显然不是新问题,但似乎123等相关问题也在等待答案。

(附注:除了this 似乎有一些我可以使用的信息)

所以我的问题是:我如何将这个带有 FlexJSON 的 JSON 解析成一个不仅由 Maps 构成的结构?

【问题讨论】:

  • 它不仅仅是地图——那里至少有一个数组。
  • @HotLicks true :-) 但我认为如果我们可以用 POJO 替换地图,列表就不会打扰
  • 我发现Map&lt;String,Object&gt; 更容易理解(和输入)。

标签: java json wadl json-deserialization


【解决方案1】:

没有任何Map的工作解决方案:

让我们定义类自下而上

1.目标:


public class Target {

private String uri;
private String type;
private String name;
private String host;
private String domain;
private String description;

public String getUri() {
    return uri;
}

public void setUri(String uri) {
    this.uri = uri;
}

public String getType() {
    return type;
}

public void setType(String type) {
    this.type = type;
}

public String getName() {
    return name;
}

public void setName(String name) {
    this.name = name;
}

public String getHost() {
    return host;
}

public void setHost(String host) {
    this.host = host;
}

public String getDomain() {
    return domain;
}

public void setDomain(String domain) {
    this.domain = domain;
}

public String getDescription() {
    return description;
}

public void setDescription(String description) {
    this.description = description;
}
}

该类表示以下 JSON:

 "target": {
        "uri": "https://opam_server_host:opam_ssl_port/opam/target/9bbcbbb087174ad1900ea691a2573b61",
        "type": "ldap",
        "name": "person1-ldap",
        "host": "opam_server_host",
        "domain": "berkeley",
        "description": "Ldap target"
      }

2。 TargetWrapper:

注意target 在大括号内。这个类只是简单地包装了它。

public class TargetWrapper {

    private Target target;

    public Target getTarget() {
        return target;
    }

    public void setTarget(Target target) {
        this.target = target;
    }
 }

该类表示以下 JSON:

{
      "target": {
        "uri": "https://opam_server_host:opam_ssl_port/opam/target/9bbcbbb087174ad1900ea691a2573b61",
        "type": "ldap",
        "name": "person1-ldap",
        "host": "opam_server_host",
        "domain": "berkeley",
        "description": "Ldap target"
      }
    }

3。 RestApiResponse

这个类代表你的api返回的整个JSON

public class RestApiResponse {

    @JSON(name="Target Collection")
    private List<TargetWrapper> targetCollection = new ArrayList<TargetWrapper>();

    @JSON(name="Target Collection")
    public List<TargetWrapper> getTarget_Collection() {
        return targetCollection;
    }
    @JSON(name="Target Collection")
    public void setTarget_Collection(List<TargetWrapper> tc) {
        this.targetCollection = tc;
    }

}

4.让我们测试一下吧!

public static void main(String[] args) {


        JSONDeserializer<RestApiResponse> js = new JSONDeserializer<RestApiResponse>();


        String input="{\"Target Collection\":[{\"target\":{\"uri\":\"https://opam_server_host:opam_ssl_port/opam/target/9bbcbbb087174ad1900ea691a2573b61\",\"type\":\"ldap\",\"name\":\"person1-ldap\",\"host\":\"opam_server_host\",\"domain\":\"berkeley\",\"description\":\"Ldap target\"}},{\"target\":{\"uri\":\"https://opam_server_host:opam_ssl_port/opam/target/ac246a162ce948c7b1cdcc17dfc92c15\",\"type\":\"ldap\",\"name\":\"person1-ldap2\",\"host\":\"opam_server_host:opam_ssl_port\",\"domain\":\"berkeley\",\"description\":\"Ldap target\"}}]}";

        RestApiResponse restApiResponse=js.deserialize(input,RestApiResponse.class);

        System.out.println(new JSONSerializer()
        .exclude("*.class").deepSerialize(restApiResponse));


    }

输出:

{
  "Target Collection": [
    {
      "target": {
        "description": "Ldap target",
        "domain": "berkeley",
        "host": "opam_server_host",
        "name": "person1-ldap",
        "type": "ldap",
        "uri": "https://opam_server_host:opam_ssl_port/opam/target/9bbcbbb087174ad1900ea691a2573b61"
      }
    },
    {
      "target": {
        "description": "Ldap target",
        "domain": "berkeley",
        "host": "opam_server_host:opam_ssl_port",
        "name": "person1-ldap2",
        "type": "ldap",
        "uri": "https://opam_server_host:opam_ssl_port/opam/target/ac246a162ce948c7b1cdcc17dfc92c15"
      }
    }
  ]
}

希望对你有帮助。

【讨论】:

  • 这个注解@JSON是什么?
  • 我明白了.. 你使用的是 flexjson 3.2!
  • @Leo 我没有注意到版本。你不能用那个版本吗?
【解决方案2】:

哦,看看这个

    JSONDeserializer<Map<String,List<MetaTarget>>> j = new JSONDeserializer<>();
    List<MetaTarget> l = j.use("values.values", MetaTarget.class) //magic that means that the item inside a list (values #1) inside a map (values #2) is a MetaTarget
    .deserialize(new InputStreamReader(JSONParser.class.getResourceAsStream("sample.json")),Map.class) //have no idea what Map does here
    .get("Target Collection"); //since deserializer returns a map, use this get to return a map value, in this case, a List

    for(MetaTarget mt : l){
        System.out.println(mt.getTarget());
        mt.getTarget().getHostname(); //I can access the attribute... thanks god
    }

在哪里

public class MetaTarget {
    private Target target;

    public Target getTarget() {
        return target;
    }

    public void setTarget(Target target) {
        this.target = target;
    }
}

public class Target {

    /**
     * uri is the target resource URI.
     */
    private String  uri;

    /**
     * type is the target type.
     */
    private String  type;

    /**
     * hostname is the target's host name.
     */
    private String  hostname;

    /**
     * name is the target name.
     */
    private String  name;

    /**
     * org is the target's organization.
     */
    private String  org;

    /**
     * domain is the target's domain.
     */
    private String  domain;

    /**
     * description is a description of the target system.
     */
    private String  description;

    public String getUri() {
        return uri;
    }

    public void setUri(String uri) {
        this.uri = uri;
    }

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public String getHostname() {
        return hostname;
    }

    public void setHostname(String hostname) {
        this.hostname = hostname;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public String getOrg() {
        return org;
    }

    public void setOrg(String org) {
        this.org = org;
    }

    public String getDomain() {
        return domain;
    }

    public void setDomain(String domain) {
        this.domain = domain;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    @Override
    public String toString() {
        return "Target [uri=" + uri + ", type=" + type + ", hostname=" + hostname + ", name=" + name + ", org=" + org + ", domain=" + domain + ", description=" + description + "]";
    }

}

更少的地图!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2023-03-05
    • 2023-02-05
    • 2021-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-01
    相关资源
    最近更新 更多