动态 JSON 结构到 Java 结构

2023-12-06

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

我能找到的关于将 JSON 转换为 Java 的所有资源都基于这样的想法:您必须首先在 Java 中手动构建对象(PO​​JO),然后使用 JSON 来填充它。

作为一名网络语言老手,我对这个想法感到窒息。我知道编译语言的玩法不同,但我认为这是从命令行到机器语言的开发人员共享的一个原则:“如果你必须做两次以上,那就自动化它。”

...然而,Java 的主要智慧似乎是:每次都手动构建繁琐的结构,然后使用 GSON/Jackson/任何东西来填充刚性结构。如果您的 JSON 发生变化(而且它会发生变化,因为 JSON),请重新执行整个操作。

是否有类似于网络代码的思维方式?
1)加载JSON
2)基于JSON结构构建原生语言结构。
3) 使用结构中的数据填充新对象。
4)随心所欲地使用对象。

(正如 @Thomas 指出的,为什么需要这样做的最准确场景是返回 JSON 的 API 响应,它可能会定期不同,虽然鸭子类型对于高级语言来说通常不舒服,但即使将所有内容都转换为字符串也可以保存与每次重建框架相比需要付出的努力和时间{或者拥有一个工具可以将无数来源的 JSON 转换为可供任何其他工具使用}。同样,从牛仔语言的角度来看,这似乎是显而易见的,但对于高级语言来说却很陌生人们无法理解这个问题的语言。)


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

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

以以下 google 地图 API 调用为例,该调用可获取给定地址的地理详细信息:

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

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

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

现在我终于可以给出一个解决方案:

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

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类代码取自果冻框架它可以让你做到这一点。

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;
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

动态 JSON 结构到 Java 结构 的相关文章

随机推荐

  • 重定向回来时 LightOpenID 被禁止

    我正在尝试使用 lightOpenID 它应该很简单 并且上传文件然后测试它是否有效 当我使用 example google php 时 我第一次点击登录按钮 它要求我登录 Google 并允许 记住我正在构建的网站 然后它重定向回 exa
  • 在C语言中,数组是指针还是用作指针?

    我的理解是 数组只是指向值序列的常量指针 当您在 C 中声明数组时 您就是在声明一个指针并为其指向的序列分配空间 但这让我很困惑 以下代码 char y 20 char z y printf y size is lu n sizeof y
  • 需要将ascii值转换为hex值

    我需要将 ascii 值转换为十六进制值 请参阅 Ascii 表 但我在下面列出了一些示例 ASCII 1 31 2 32 3 33 4 34 5 35 A 41 a 61 等 但我使用 int 而不是字符串值 是否可以这样做 因此int测
  • Jekyll 多页分页

    我是 html css 新手 但正在尝试使用 Jekyll 创建一个博客 我在这里找到了这个主题https github com rosario kasper 主页index html 包含分页列表中的所有帖子 这很酷 不过 我想将我的帖子
  • Grails 条件查询检查“OR”逻辑

    我有圣杯criteriaQuery我正在检查的地方OR针对单个状态变量的逻辑如下 or eq status Status ONE eq status Status TWO eq status Status THREE 这段代码工作正常 我的
  • 从 firestore flutter 中的子集合中获取数据

    在第一个屏幕截图中 收集了许多文档users 每个文档都包含进一步的集合jobPost该集合包含更多文档及其元数据 我在这里想要的是转到集合的每个文档users和进一步的子集合jobPost并获取所有文档 假设首先应该转到集合中的文档 1u
  • 将 jQuery 日期选择器应用于多个实例

    我有一个 jQuery 日期选择器控件 可以在一次实例中正常工作 但我不确定如何让它在多个实例中工作 br 如果没有 For Each 循环 它可以正常工作 但如果 MyRecords 集合中有多个项目 则只有第一个文本框获得日期选择器 这
  • Lumen - mongodb - jenssegers/laravel-mongodb - 邮递员

    我已经在我的wamp上安装了mongodb C wamp64 bin mongodb mongodb 3 4 bin 我在路径中添加了 mongodb 并创建 Windows 服务以在必要时启动它 我已经通过 Composer 安装了 lu
  • C++ 中的多维数组如何发挥作用? [复制]

    这个问题在这里已经有答案了 可能的重复 如何在 C 中使用数组 简而言之 C 中的多维数组是数组的数组 还是只是一个表现得像多维的数组 我的一位朋友解释说 C 中的数组只是常量指针 多维数组也是常量指针 其元素由多个索引寻址 即它们是指向一
  • 如何在 SQL 中选择重叠的日期范围

    我有一个包含以下列的表 sID 开始日期和结束日期 一些值如下 1 1995 07 28 2003 07 20 1 2003 07 21 2010 05 04 1 2010 05 03 2010 05 03 2 1960 01 01 201
  • java中的“>>>”是什么意思?

    我试图将此代码翻译为Python 但我很难这样做 不要担心索引值和变量名称 我只是想知道 gt gt gt 部分到底做了什么 也许是Python的等效项 但有一个解释就很好了 target 0 char source sourceIndex
  • 循环 tf.data.Dataset 非常慢

    我想知道为什么对 tf data Dataset 样本进行 for 循环比对相应的 numpy 数组进行循环要慢得多 import numpy as np import tensorflow as tf import time a np o
  • 如何在 Java 中从 List 转换为 double[]?

    我有一个这样的变量 List
  • 如何将 Next.js Link 与多个子项一起使用?

    如何使用Link在 Next js 中有多个 div 里面这个 div 我有 img 标签Link 链接的段落 链接的标题 错误 多个孩子被传递给href of article但只支持一个孩子https nextjs org docs me
  • 为什么 Xcode 中 Storyboard 的背景颜色没有改变?总是相同的灰色吗?

    因此 我已将故事板文件中默认视图的背景属性更改为与彩虹中的颜色一样多 颜色在 Xcode 中与我的按钮一起很好地显示 但是当我实际运行应用程序时 背景始终是与您从新 Xcode 项目开始时相同的 难看的 默认的灰色 Hello World
  • Cin.Ignore() 不起作用

    这里我有一个代码 cout lt lt Press Enter To Exit cin ignore 该程序将执行并等待 直到您按 Enter 键 然后它才会退出 现在看这段代码 int m cin gt gt m cout lt lt P
  • 自定义类加载器问题

    接下来的问题是 我从以下位置获取了基类加载器代码here 但我的类加载器在某种程度上是特定的 它必须能够从文件系统加载类 让我们以WinOS为例 所以在类加载器中必须有一些setAdditionalPath 方法 它设置一个路径 文件系统上
  • 将正确的 Gcode 字符串发送到串行端口?

    我正在尝试发送 gcodeg28通过线路连接到我的 RepRap 3D 打印机port Write g28 我的程序连接到正确的串行端口 但是当我尝试以字符串形式发送信息时 对 com 端口的访问被拒绝 这很奇怪 因为在向串行端口发送 Gc
  • 带有 utf-8 的 php substr() 函数在末尾留下 � 标记

    这是简单的代码
  • 动态 JSON 结构到 Java 结构

    我正在开发一个项目 使用 JSON 作为创建 Java 对象的配置框架 这也是我的第一个专业 Java 项目 来自多年的 CF PHP JS 等经验 我能找到的关于将 JSON 转换为 Java 的所有资源都基于这样的想法 您必须首先在 J