如何使用存储过程中的数组进行嵌套 JSON 响应

How to make nested JSON response with Array from a Stored procedure

我有一个从存储过程生成的数据集

+------+--------+---------------------+------------+
| Line |Status  | Consent             | tid        |
+------+--------+---------------------+------------+
| 1001 | 1      | Yes                 | 1054       |
| 1002 | 1      | yes                 | 1055       |
| 1003 | 1      | Yes                 | 3045       |
| 1004 | 1      | No                  | 3046       |
| 1005 | 0      | No                  | 1023       |
| 1006 | 0      | Yes                 | 1024       |
| 1007 | 1      | No                  | 1025       |
+------+--------+---------------------+------------+

我希望能够根据从存储过程中获得的数据生成一个 JSON

{
    "totalMembers": 9,
    "questionaryinfo": [
        {
            "line": "1001",
            "status": "1",
            "consent": "Yes",
            "tid": "1054",
            "adultquestionary":"Yes"
        },
        {
            "line": "1002",
            "status": "1",
            "consent": "Yes",
            "tid": "1055",
            "adultquestionary":"Yes"
        },
        {
            "line": "1003",
            "status": "1",
            "consent": "Yes",
            "tid": "3035",
            "adultquestionary":"Yes"
        },
}

我试过使用哈希映射

public ResponseEntity> retrieveLineListing(String Case){

    StoredProcedureQuery query = entityManager.createStoredProcedureQuery("get_listing", "ListingModel");
    query.registerStoredProcedureParameter("Case", String.class, ParameterMode.IN);
    query.setParameter("Case", Case);
    query.execute();

    List list = query.getResultList();

    Map<String, Object> parent = new HashMap<>();
    parent.put("totalMembers", 9);

    parent.put("questionaryinfo", new HashMap<String, Object>());
  parent.put("questionaryinfo", new ArrayList<HashMap<String,Object>>());
ArrayList<HashMap<String,Object>> listings = (ArrayList<HashMap<String,Object>>) parent.get("questionaryinfo");
if (list != null) {
    list.forEach(d -> {
        HashMap<String,Object> entry = new HashMap<>();

        entry.put("adultquestionary","Yes");
        entry.put("consent", list.get(1));
        listings.add(entry);
    });
}
    return ResponseEntity.ok().body(parent);
}

更新 1

修改@Rahul 建议我做的事情后,

我的JSON长得像

{
    "totalMembers": 9,
    "questionaryinfo": [
      "consent"{
        {
            "line": "1001",
            "status": "1",
            "consent": "Yes",
            "tid": "1054",
          
        },
        "adultquestionary":"Yes"
      }
      "consent"{
        {
            "line": "1002",
            "status": "1",
            "consent": "Yes",
            "tid": "1055",
        },
        "adultquestionary":"Yes"
      },
      "consent"{
        {
            "line": "1003",
            "status": "1",
            "consent": "Yes",
            "tid": "3035",
        },
        "adultquestionary":"Yes"
      },
      ]
    }
    

如何设置我的方法来生成上面的嵌套 JSON 并获取线路、状态、同意和 tid 值?

没试过,但应该运行:

parent.put("questionaryinfo", new ArrayList<HashMap<String,Object>>());
ArrayList<HashMap<String,Object>> listings = (ArrayList<HashMap<String,Object>>) parent.get("questionaryinfo");
if (list != null) {
    list.forEach(d -> {
        HashMap<String,Object> entry = new HashMap<String,Object>();
        
        entry.put("adultquestionary","Yes");
        entry.put("consent", list.get(0));
        listings.add(entry);
    });
}
    

我建议您将 DTO 模型 用于 请求 响应 作为在您的 Resource/Controller 图层中进行更好的练习。您仍然需要使用存储过程响应正确填充模型,但从我在您的 post.

中看到的内容来看,这应该不是一个挑战

将响应格式封装到单个模型中的真正好处是 灵活性可扩展性各种回应 你 API 可能 return.

为了让您检索上面定义的有效载荷,它必须像这样简单:

@RestController
@RequestMapping("/v1/Whosebug")
public class DemoController {

    @GetMapping
    public ResponseEntity<ResponseDTO> read() {
        List<Consent> result = mockStoreProcedureResult();
        ResponseDTO response = ResponseDTO.builder()
                .totalMembers(result.size())
                .questionaryInfo(result)
                .build();
        return ResponseEntity.ok(response);
    }

}

其中 ResponseDTO 模型封装了您想要的响应形状。您会看到我还创建了一个反映您最初提议的 Consent 模型。

@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder(toBuilder = true)
public class ResponseDTO {
    private Integer totalMembers;
    private List<Consent> questionaryInfo;
}


@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder(toBuilder = true)
public class Consent {
     private String line;
     private String status;
     private String consent;
     private String tid;
     private String adultQuestionary;
}

当我 运行 演示应用程序并发出请求时,我得到了与您正在寻找的内容类似的响应。如果我想改变 questionaryInfo 中对象的格式,就像编辑用于此目的的模型一样简单。

curl -X GET --location "http://localhost:8080/v1/Whosebug" \
    -H "Content-Type: application/json"

HTTP/1.1 200 
Content-Type: application/json
Transfer-Encoding: chunked
Date: Tue, 29 Jun 2021 18:35:11 GMT
Keep-Alive: timeout=60
Connection: keep-alive

{
  "totalMembers": 3,
  "questionaryInfo": [
    {
      "line": "1001",
      "status": "1",
      "consent": "Yes",
      "tid": "1054",
      "adultQuestionary": "Yes"
    },
    {
      "line": "1002",
      "status": "1",
      "consent": "Yes",
      "tid": "1055",
      "adultQuestionary": "Yes"
    },
    {
      "line": "1003",
      "status": "1",
      "consent": "Yes",
      "tid": "3055",
      "adultQuestionary": "Yes"
    }
  ]
}

希望你觉得这有用,干杯。

编辑: 回答你的问题@arriff,你如何为你的响应模型注入值?

您可以轻松地遍历从存储过程返回的列表并将每个条目映射到模型中。为此,必须在您的模型中定义一个可以接收预期参数的构造函数。

public List<Consent> getConsentAnswers() {
    return dbStoreProcedureResult().stream()
            .map(dbo -> new Consent(dbo, "Yes", "Yes"))
            .collect(Collectors.toList());
}

这是为 Consent 模型定义的附加自定义构造函数。

public Consent(@NonNull DBConsent dbo,
               @NonNull String consent,
               @NonNull String adultQuestionary) {
     this.line = dbo.getLine();
     this.tid = dbo.getTid();
     this.status = dbo.getStatus();
     this.consent = consent;
     this.adultQuestionary = adultQuestionary;
}