【问题标题】:Json object values manipulation in Spring-bootSpring-boot中的Json对象值操作
【发布时间】:2018-12-11 12:27:03
【问题描述】:

我有一个示例 json 如下

[{"state":"Completed","mignum":146289,"projectleader":"Eric Lok","productiondate":"Jun 6, 2018","installationtiers":"Windows Server","targetplatform":"Production","apprelated":"UPS Pickup Point Web Application","appversion":"2.25"},
{"state":"Completed","mignum":146381,"projectleader":"James Rice","productiondate":"Jun 6, 2018","installationtiers":"Linux Web WL10","targetplatform":"Production","apprelated":"Content Only","appversion":""},
{"state":"Pending Migration to Production","mignum":146461,"projectleader":"Nishith Jani","productiondate":"Jun 6, 2018","installationtiers":"Linux BEA WL12","targetplatform":"Production","apprelated":"Tracking Comp","appversion":"1801.20"},
{"state":"Completed","mignum":146574,"projectleader":"Nishith Jani","productiondate":"Jun 6, 2018","installationtiers":"Linux BEA WL12","targetplatform":"Production","apprelated":"Tracking Comp","appversion":"01-00-07-17"}
{"state":Pending Approval by Development in Windward","mignum":146289,"projectleader":"Eric Lok","productiondate":"Jun 6, 2018","installationtiers":"Windows Server","targetplatform":"Production","apprelated":"UPS Pickup Point Web Application","appversion":"2.25"},
{"state":"Completed","mignum":146381,"projectleader":"James Rice","productiondate":"Jun 6, 2018","installationtiers":"Linux Web WL10","targetplatform":"Production","apprelated":"Content Only","appversion":""},
{"state":"Pending Approval by Development in Windward","mignum":146461,"projectleader":"Nishith Jani","productiondate":"Jun 6, 2018","installationtiers":"Linux BEA WL12","targetplatform":"Production","apprelated":"Tracking Comp","appversion":"1801.20"},
{"state":"Pending Migration to Production","mignum":146574,"projectleader":"Nishith Jani","productiondate":"Jun 6, 2018","installationtiers":"Linux BEA WL12","targetplatform":"Production","apprelated":"Tracking Comp","appversion":"01-00-07-17"}
]

我在 Spring 中使用 jdbc 连接从 db 获得

@GetMapping("/dashboard")
public String Data() {
    Connection conn = null;
    List<Map<String, Object>> listOfDates = null;
    try {
        Class.forName("com.mysql.jdbc.Driver");
        conn = DriverManager.getConnection(DB_URL, USER, PASS);
        String countQuery = "SELECT migrations.mignum, migration_states.statemigrations.projectleader, migrations.productiondate, migrations.installationtiers, migrations.targetplatform, migrations.apprelated, migrations.appversion FROM migrations, migration_states WHERE migrations.productiondate='2018-07-07";
        QueryRunner queryRunner = new QueryRunner();
        listOfDates = queryRunner.query(conn, countQuery, new MapListHandler());
        conn.close();
    } catch (SQLException se) {
        se.printStackTrace();
    } catch (Exception e) {
        e.printStackTrace();
    } finally {
        DbUtils.closeQuietly(conn);
    }
    return new Gson().toJson(listOfDates);
}

我想解析结果并将其保存在另一个json中,如下所示 1. 第一个结果

[
{
"state":"Completed"
"value": [
    {"mignum":146289,"projectleader":"Eric Lok","productiondate":"Jun 6, 2018","installationtiers":"Windows Server","targetplatform":"Production","apprelated":"UPS Pickup Point Web Application","appversion":"2.25"};
    {"mignum":146381,"projectleader":"James Rice","productiondate":"Jun 6, 2018","installationtiers":"Linux Web WL10","targetplatform":"Production","apprelated":"Content Only","appversion":""},
    {"mignum":146381,"projectleader":"James Rice","productiondate":"Jun 6, 2018","installationtiers":"Linux Web WL10","targetplatform":"Production","apprelated":"Content Only","appversion":""}
]
}
{
"state":"Pending Migration to Production"
"value": [
    {"mignum":146461,"projectleader":"Nishith Jani","productiondate":"Jun 6, 2018","installationtiers":"Linux BEA WL12","targetplatform":"Production","apprelated":"Tracking Comp","appversion":"1801.20"}.
    {"mignum":146574,"projectleader":"Nishith Jani","productiondate":"Jun 6, 2018","installationtiers":"Linux BEA WL12","targetplatform":"Production","apprelated":"Trackin Comp","appversion":"01-00-07-17"}
]
}
{
"state":"Pending Approval by Development in Windward"
"value": [
    {"mignum":146461,"projectleader":"Nishith Jani","productiondate":"Jun 6, 2018","installationtiers":"Linux BEA WL12","targetplatform":"Production","apprelated":"Tracking Comp","appversion":"1801.20"}.
    {"mignum":146574,"projectleader":"Nishith Jani","productiondate":"Jun 6, 2018","installationtiers":"Linux BEA WL12","targetplatform":"Production","apprelated":"Trackin Comp","appversion":"01-00-07-17"}
]
}
]

2。第二个结果

[
  { "state":"Completed", "count": "2"},
  { "state":"Pending Migration to Production", "count": "2"},
  { "state":"Pending Approval by Development in Windward", "count": "2"}
]

我是 Java/Spring 方面这种 json 操作的新手,所以任何人都可以帮助我,因为我很长时间都被困在这一点上

【问题讨论】:

  • 您可以使用 DTO 投影。例如具有属性状态和值映射的 StateDTO。
  • migrationsmigration_states是什么关系?
  • migration_states 来自 DB 的迁移表
  • 您应该停止考虑 JSON 操作以及 Map。相反,创建一个类来表示您从数据库中读取的内容。创建另一个表示您要生成的 JSON 结构的类,并使用 Jackson 注释映射到 JSON。然后从数据库中读取数据,创建第一类的实例;将这些对象转换为第二类的实例,并要求杰克逊将这些第二类的实例写为 JSON。
  • @JB Nizet 我理解你所说的整体,但不自信。你能添加一些类似的代码来理解你在说什么吗?

标签: java json spring spring-boot gson


【解决方案1】:

与使用普通 JDBC 相比,使用 JPA(+ Spring Data)可能更有趣,因为这允许您使用类/对象而不是映射,例如:

@Entity
@Table(name = "migrations")
public class Migration {
    @Id
    private Long mignum;
    private LocalDate productiondate;
    private String installationtiers;
    private String targetplatform;
    private String apprelated;
    private String appversion;
    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "mignum")
    private MigrationState state;

    // Getters + Setters
}

@Entity
@Table(name = "migration_states")
public class MigrationState {
    @Id
    private Long mignum;
    private String state;
    private String projectleader;

    // Getters + Setters
}

要进行查询,您可以创建存储库并使用 JPQL:

public interface MigrationRepository extends JpaRepository<Migration, Long> {
    List<Migration> findByProductiondate(LocalDate productiondate);
}

这些类(MigrationMigrationState)代表您的数据库模型。由于您的问题不包含所有与数据库相关的信息(仅包含您编写的查询),因此您的情况可能会略有不同。

注意:您实际上并不需要 JPA,这个答案的大部分也可以在没有 JPA 的情况下使用,但是您必须在 Map&lt;String, Object&gt;Migration 之间进行映射自己一个人。

但是,除了这些类之外,您还需要代表您喜欢的输出的类。例如,这适用于您的第二个输出:

public class SimpleStateSummaryDTO {
    private String state;
    private int count;
}

这将适用于您的第一个输出:

public class StateSummaryDTO {
    private String state;
    private List<MigrationDTO> value;

    // Getters + Setters
}

与其使用代表数据库的Migration 类,不如创建一个新类来代表JSON 中的迁移,我们可以称之为MigrationDTO

public class MigrationDTO {
    private Long mignum;
    private String projectleader;
    private LocalDate productiondate;
    private String installationtiers;
    private String targetplatform;
    private String apprelated;
    private String appversion;

    // Getters + Setters
}

注意:一个DTO代表Data Ttransfer Object,代表数据是用于两个进程之间的通信,在你的情况下是你的 API 和你的消费者。

现在您有了这些类,您可以使用 Java 8 函数式 API 按其状态对 Migration 类进行分组,例如:

repository
    .findByProductiondate(LocalDate.of(2018, 6, 6)).stream()
    .collect(Collectors.groupingBy(migration -> migration.getState().getState()))

但是,这将返回 Map&lt;String, List&lt;Migration&gt;&gt;,这不是您想要的。现在您可以编写自己的收集器,也可以再次流式传输此映射,以便将其映射到您需要的位置。

例如,对于第二个输出将变为:

repository
    .findByProductiondate(LocalDate.of(2018, 6, 6)).stream()
    .collect(Collectors.groupingBy(migration -> migration.getState().getState()))
    .entrySet().stream()
    .map(entry -> new SimpleStateSummaryDTO(entry.getKey(), entry.getValue().size()))
    .collect(Collectors.toList());

我们在这里所做的是,对于每个 Map.Entry&lt;String, List&lt;Migration&gt;&gt;,我们正在创建一个新的 SimpleStateSummaryDTO,其中包含列表的状态和大小。

另一方面,第一个输出需要MigrationMigrationDTO 的额外映射:

repository
    .findByProductiondate(LocalDate.of(2018, 6, 6)).stream()
    .collect(Collectors.groupingBy(migration -> migration.getState().getState()))
    .entrySet().stream()
    .map(entry -> new StateSummaryDTO(
        entry.getKey(),
        entry.getValue().stream()
            .map(migration -> new MigrationDTO(
                migration.getMignum(),
                migration.getState().getProjectleader(),
                migration.getProductiondate(),
                migration.getInstallationtiers(),
                migration.getTargetplatform(),
                migration.getApprelated(),
                migration.getAppversion()))
        .collect(Collectors.toList())))
.collect(Collectors.toList());

注意:您不需要 Java 8 函数式 API,您可以使用循环编写一些传统逻辑。这只是让它更容易一些。

现在您已经将所需的输出作为对象,您已经完成了很多,因为 Spring 会使用 Jackson 自动将对象转换为 JSON,例如:

@GetMapping
public List<SimpleStateSummaryDTO> findSimple() {
    return repository
        .findByProductiondate(LocalDate.of(2018, 6, 6)).stream()
        .collect(Collectors.groupingBy(migration -> migration.getState().getState()))
        .entrySet().stream()
        .map(entry -> new SimpleStateSummaryDTO(entry.getKey(), entry.getValue().size()))
        .collect(Collectors.toList());
}

【讨论】:

  • 非常感谢。这就是我一直在寻找的。您的解决方案实际上帮助了我。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-07-16
  • 2017-12-04
  • 2021-02-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多