在java中将对象列表转换为JSON数组 - Spring Boot api测试

Posted

技术标签:

【中文标题】在java中将对象列表转换为JSON数组 - Spring Boot api测试【英文标题】:Convert list of Objects to JSON Array in java - Spring Boot api testing 【发布时间】:2022-01-06 06:39:50 【问题描述】:

当我尝试发出 mockmvc 发布请求时,我必须在内容标签中传递对象列表,问题是每次我尝试使用 此方法 传递它:

public static String asJsonString(final Object obj) 
        try 
            final ObjectMapper mapper = new ObjectMapper();
            final String jsonContent = mapper.writeValueAsString(obj);
            return jsonContent;
         catch (Exception e) 
            throw new RuntimeException(e);
        
    

我收到此错误

"status":"NOT_ACCEPTABLE","errors":"timestamp":"2021-11-29T11:53:11.2020882Z","message":"Wrong message format","details":"JSON parse error: Cannot deserialize instance of `java.util.ArrayList<Compania>` out of START_OBJECT token; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `java.util.ArrayList<Compania>` out of START_OBJECT token\n at [Source: (PushbackInputStream); line: 1, column: 1]"

我为仅保存 1 个对象所做的测试运行良好,但每当我尝试添加列表时它就会中断,这里有我的测试代码。

@Test
    void successSavePostCompaniaLista() throws Exception 
        Compania c1 = new Compania("Compania1 list",
            "name1",
            "---",
            "---",
            null,
            null);
        Compania c2 = new Compania("Compania2 list",
            "name2",
            "---",
            "---",
            null,
            null);

        List<Compania> companias = List.of(c1,c2);
        when(companiaRepository.save(any(Compania.class))).then(returnsFirstArg());

        this.mockMvc.perform(
                post("/companias/lista")
                    .header("authorization", "Bearer " + token)
                    .content(asJsonString(companias)) //<-- Here gives me errors
                    .contentType(MediaType.APPLICATION_JSON))
            .andDo(print())
            .andExpect(status().isCreated())
            .andExpect(jsonPath("$.result[0].success[0]").isNotEmpty())
            .andExpect(jsonPath("$.result[0].success[0].name").value(c1.getName()))
            .andExpect(jsonPath("$.result[0].success[1].name").value(c2.getName()));

    

工作原理与此类似,但只使用一个对象。

http的方向,其余的都ok。

谢谢!

编辑。这是我正在尝试测试的服务

public Map<String, Object> postListCompanias(List<Compania> companias) 
        for (int i = 0; i < companias.size(); i++) 
            Compania companiaN = companias.get(i);
            companiaN.setId(null);

            companiaRepository.save(companias.get(i));
            System.out.println(companias.get(i));
        

        Map<String, Object> mappedResult = Collections.singletonMap(
            "result",
            List.of(
                Collections.singletonMap(
                    "success",
                    companias
                )
            )
        );
        return mappedResult;
    

这里是控制器

@ResponseStatus(HttpStatus.CREATED)
    @PostMapping("/lista")
    public Map<String, Object> createCompanias(@RequestBody List<Compania> companias) 

        return companiaService.postListCompanias(companias);
    

【问题讨论】:

您能否为您要测试的控制器添加代码?谢谢! @JoãoDias 抱歉回复晚了,我已经编辑了我的帖子 【参考方案1】:

在我看来,问题在于您试图将类似以下 JSON 的内容传递给content

[
  
    "compania1_list": "Compania1 list",
    "name1": "name1",
    "s": "---",
    "s1": "---",
    "o": null,
    "o1": null
  ,
  
    "compania1_list": "Compania2 list",
    "name1": "name2",
    "s": "---",
    "s1": "---",
    "o": null,
    "o1": null
  
]

这是一个带有 2 个 JSON 对象的 JSON 数组,而不是一个带有 2 个 JSON 对象的 JSON 数组的 JSON 对象。我的猜测是 MockHttpServletRequestBuilder.content() 方法不期望这样的 JSON。

话虽如此,我会将您的控制器更改为接受对象而不是集合,如下所示:

@ResponseStatus(HttpStatus.CREATED)
@PostMapping("/lista")
public Map<String, Object> createCompanias(@RequestBody CompaniasCreationRequest companiasCreationRequest) 
    return companiaService.postListCompanias(companiasCreationRequest.getCompanias());

如下CompaniasCreationRequest

public class CompaniasCreationRequest 
    private List<Compania> companias;

    public CompaniasCreationRequest(List<Compania> companias) 
        this.companias = companias;
    

    public List<Compania> getCompanias() 
        return companias;
    

    public void setCompanias(List<Compania> companias) 
        this.companias = companias;
    

在您的测试中,这将意味着以下更改:

@Test
void successSavePostCompaniaLista() throws Exception 
    Compania c1 = new Compania("Compania1 list",
        "name1",
        "---",
        "---",
        null,
        null);
    Compania c2 = new Compania("Compania2 list",
        "name2",
        "---",
        "---",
        null,
        null);

    CompaniasCreationRequest companiasCreationRequest = new CompaniasCreationRequest(List.of(c1,c2));
    
    when(companiaRepository.save(any(Compania.class))).then(returnsFirstArg());

    this.mockMvc.perform(
            post("/companias/lista")
                .header("authorization", "Bearer " + token)
                .content(asJsonString(companiasCreationRequest))
                .contentType(MediaType.APPLICATION_JSON))
        .andDo(print())
        .andExpect(status().isCreated())
        .andExpect(jsonPath("$.result[0].success[0]").isNotEmpty())
        .andExpect(jsonPath("$.result[0].success[0].name").value(c1.getName()))
        .andExpect(jsonPath("$.result[0].success[1].name").value(c2.getName()));

现在您的请求正文将如下所示(这是一种更标准的 JSON 格式):


  "companias": [
    
      "compania1_list": "Compania1 list",
      "name1": "name1",
      "s": "---",
      "s1": "---",
      "o": null,
      "o1": null
    ,
    
      "compania1_list": "Compania2 list",
      "name1": "name2",
      "s": "---",
      "s1": "---",
      "o": null,
      "o1": null
    
  ]

【讨论】:

以上是关于在java中将对象列表转换为JSON数组 - Spring Boot api测试的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Angular 2 中将对象转换为 JSON 列表?

在 Laravel 中将二维数组转换为 json 对象

如何在android中将json对象从json数组转换为字符串数组

在Javascript中将JSON字符串转换为JSON对象数组

在 Swift 4 中将 Json 对象转换为数组格式

如何在 Javascript 中将表单数组转换为 JSON? (对象数组)?