动态JSON结构到Java结构 [英] Dynamic JSON structure to Java structure

查看:91
本文介绍了动态JSON结构到Java结构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个项目,使用JSON作为创建Java对象的配置框架。这也是我在CF / PHP / JS等方面多年经验的第一个专业Java项目...

I'm working on a project to use JSON as a configuration framework for creating Java objects. This is also my first professional Java project coming from years of experience in CF/PHP/JS etc...

我可以找到将JSON转换为Java的每个资源都是预测的关于你必须首先用Java手动构建对象的想法,POJO然后使用JSON来填充它。

EVERY resource I can find on converting JSON to Java is predicated on the idea that you have to manually build the object in Java first, a POJO, and then use the JSON to populate it.

作为一名网络语言老手,我'我对这个想法感到窒息。我认为编译语言的播放方式不同,但我认为这是从命令行到机器语言共享的一个原则:如果你必须做两次以上,那就自动完成。

As a web language veteran, I'm choking on this idea. I get that compiled languages play differently, but I thought it was a tenet developers from command line to machine language shared: "If you have to do it more than twice, automate it."

......然而看起来主流的Java智慧似乎是:每次都手工构建繁琐的结构,然后使用GSON / Jackson /无论如何填充刚性结构。如果你的JSON发生了变化(并且它会因为JSON而重新完成)。

...and yet it seems like the presiding Java wisdom is: Do the tedious structure building by hand, every time, then use GSON/Jackson/whatever to populate the rigid structure. If your JSON changes (and it will, because JSON) do the whole thing over again.

是否与Web代码的思维方式并行?

1)加载JSON

2)基于JSON结构构建本机语言结构。

3)用结构中的数据填充新对象。

4根据你的意愿使用对象。

Is there a parallel to the web code way of thinking?
1) Load JSON
2) Build native language structure based on JSON structure.
3) Populate new object with data from structure.
4) Use object however you wish.

(正如@Thomas所指出的,为什么这是必要的最准确的场景是返回JSON的API响应,它可能是定期不同,虽然鸭子打字对于高级语言来说通常不舒服,但每次将一切转换为字符串与每次重建框架相比节省了工作量和时间{或者有一个工具可以将您的JSON从无数来源转换为可供任何其他人使用从牛仔语言的角度来看,它似乎很明显,但对于高级语言来说,人们并不理解这个问题。)

(As @Thomas pointed out, the most accurate scenario for why this would be necessary is a API response that returns JSON, it might be different periodically, and while duck typing is generally uncomfortable for high level languages, even converting EVERYTHING to a string saves effort and time compared to rebuilding your framework every time {or having a tool that converts your JSON from myriad sources to be usable by any other tool}. Again, it seems obvious from the perspective of cowboy languages, but so foreign to the high level languages people aren't understanding the question.)

推荐答案

我仔细阅读了上面的评论,我认为有一个非常常见的情况是,即使在编译时已知API结构, ad hoc Java对象也非常有用。

I read carefully the comments above and I think there is a very common scenario where an ad hoc Java object would be extremely useful even if the API structure is known at compile time.

让我们假设您处理的API返回一个复杂的JSON对象,您只对非常具体的属性值感兴趣。

Lets say you deal with an API that return a complex JSON object in which you are only interested in a very specific property value.

以下面的谷歌地图API调用为例,获取地理位置详细信息:

Take as an example the folowing google map API call to get geo details givin an address:

https://maps.googleapis.com/maps/api/geocode/json?address=sunnyvale,CA

正如您可以查看的那样,响应结构非常复杂。假设您只想获得 lat lng 属性值,应该有一种更简单的方法,而不是预定义完整相应的Java类。

As you can check and see, the response structure is quite complex. Assuming you only want to get the lat and lng properties value, there should be an easier way rather than predefine the complete corresponding Java class.

所以是的,如果您不想使用强类型预定义Java类,则需要使用原始对象类型和映射。更具体地说,是一个StringMap。

So yes, if you don't want to go with the strongly typed predefined Java class, you will need to use raw Object type and Maps. More specifically, a StringMap.

现在最后我可以给出一个解决方案:

And now finally I can give a solution:

理想情况下,你想要使用与JS中相同的本机表示法访问属性。这样的事情:

Ideally, you would like to access the properties with the same native notation like you would do in JS. Something like this:

String url = "https://maps.googleapis.com/maps/api/geocode/json?address=" + address;
String responseStr = fetch(url);
JsonHelper response =  JsonHelper.forString(responseStr);

String status = (String) response.getValue("status");
if(status != null && status.equals("OK")) {
   lat = (Double) response.getValue("results[0].geometry.location.lat");        
   lng = (Double) response.getValue("results[0].geometry.location.lng");
}

以下 JsonHelper 类代码取自 jello-framework ,它可以让你做到这一点。

The following JsonHelper class code is taken from the jello-framework and it lets you do exactly that.

package jello.common;

import java.util.List;

import com.google.gson.Gson;
import java.util.AbstractMap;

public class JsonHelper {

    private Object json;

    public JsonHelper(String jsonString) {
        Gson g = new Gson();
        json = g.fromJson(jsonString, Object.class);
    }

    public static JsonHelper forString(String jsonString) {
        return new JsonHelper(jsonString);
    }

    @SuppressWarnings("unchecked")
    public Object getValue(String path) {
        Object value = json;
        String [] elements = path.split("\\.");
        for(String element : elements) {
            String ename = element.split("\\[")[0];

            if(AbstractMap.class.isAssignableFrom(value.getClass())) {
                value = ( (AbstractMap<String, Object>) value).get(ename);

                if(element.contains("[")) {
                    if(List.class.isAssignableFrom(value.getClass())) {
                        Integer index = Integer.valueOf(element.substring(element.indexOf("[")+1, element.indexOf("]")) );
                        value = ((List<Object>) value).get(index);
                    }
                    else {
                        return null;
                    }
                }
            }
            else {
                return null;
            }
        }

        return value;
    }
}

这篇关于动态JSON结构到Java结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆