Using @RequestBody with a Map<String, String>[] in Spring Boot results in a collection of blank elements

My client side application is built with Angular. I am attempting to send a List of Map to a Spring Boot REST API, but it seems to be getting serialized as a List of empty items. I have also tried using an array Map[] and using a Map of Objects.

Below is the POJO definition :

public class ClasseurDTO {

    private Map<String,String>[] ongletGeneralite;
    
    public ClasseurDTO() {
    }

    public Map<String, String>[] getOngletGeneralite() {
        return ongletGeneralite;
    }

    public void setOngletGeneralite(Map<String, String>[] ongletGeneralite) {
        this.ongletGeneralite = ongletGeneralite;
    }
    
    @Override
    public String toString() {
        // parse ongletGeneralite object 
        String str = "";
        for (Map<String, String> map : ongletGeneralite) {
            for (Map.Entry<String, String> entry : map.entrySet()) {
                str += entry.getKey() + " : " + entry.getValue() + " ,";
            }
        }

        return "ClasseurDTO [ongletGeneralite=" + str + "]";
    }
}

This is the typescript type def:

export type ClasseurDTO = {
     ongletGeneralite: Map<string, string>[]
}

The method definition of the API :

@PostMapping("/public/observations/import-observations")
public ResponseEntity<String> importObservations(@RequestBody ClasseurDTO classeur) {
    observationService.importObservations(classeur);
    return ResponseEntity.ok().body("Importation terminée");
}

This is the http call:

importClasseur(classeur: ClasseurDTO): Observable<HttpResponse<{}>> {
    console.log("importClasseur", classeur)
    return this.http
    .post(`${this.resourceUrlPublic}/import-observations`, classeur, { observe: 'response' });
}

Here is the log on the client side just before calling the API https://i.sstatic.net/BKwIw.png

Here is the payload in the network debug tool https://i.sstatic.net/9gBts.png

Can anyone identify where the issue lies?

Answer №1

After conducting further investigation and trying various approaches, I made a significant change to the input type by switching it to a string[][][] instead of using a List of Map. Surprisingly, this adjustment resulted in the nested items no longer being empty. To adapt to this modification, I expanded the definitions and implemented the following structure on the client side:

export class CellDataClasseur {
    cellData: string[] = []
}

export class LigneDataClasseur {
    ligneData: CellDataClasseur[] = [];
}
export class ClasseurDTO  {
     ongletGeneralite: LigneDataClasseur[] = [];

}

On the server side, I utilized the following plain old Java objects (POJO):

public class CellDataClasseur {
private List<String> cellData;

public List<String> getCellData() {
    return cellData;
}

public void setCellData(List<String> cellData) {
    this.cellData = cellData;
}
}

public class LigneDataClasseur {
private List<CellDataClasseur> ligneData;

public List<CellDataClasseur> getLigneData() {
    return ligneData;
}

public void setLigneData(List<CellDataClasseur> ligneData) {
    this.ligneData = ligneData;
}
}

public class ClasseurDTO {
private List<LigneDataClasseur> ongletGeneralite;

public List<LigneDataClasseur> getOngletGeneralite() {
    return ongletGeneralite;
}

public void setOngletGeneralite(List<LigneDataClasseur> ongletGeneralite) {
    this.ongletGeneralite = ongletGeneralite;
}
}

I am leaving the question open for discussion in case someone can provide insights on serializing Map or suggest improvements to my current solution.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Unusual Behavior of Observable.concat() in Angular 4 with RxJS 5

My Angular 4 / TypeScript 2.3 service has a method called build() that throws an error if a certain property is not initialized. I am attempting to create a safer alternative called safeBuild() that will return an Observable and wait for the property to be ...

What is the best way to retrieve the href attribute when working with cheerio?

Is there a way to retrieve the link using Cheerio in this code snippet? <div class="someClass"> <a href="someLink">Link</a> </div> I attempted to do so, but unfortunately it was unsuccessful. let link = $(&a ...

`Where can I find both the old and new values in Angular mat-select?`

Hello there. I am currently working with Angular 6 and Angular Material. I have an array of strings that I am displaying in a dropdown field using mat-select. I need to be able to track the previous value and the new value when a user selects different ele ...

Tips for preventing Angular from requiring an additional tag for a child component

Consider a scenario where I have a parent and child component in Angular 12. Their templates are structured as follows: Parent: <h1>This is the parent component</h1> <div class="container"> <div class="row"> ...

Leveraging Angular 2 and Typescript for crafting a cutting-edge Chrome application

I am currently working on developing a Chrome App using the Angular 2 5-minute quick start as a reference to create a sample application. However, I have encountered security concerns related to how system JS functions with Chrome applications. Has anyone ...

Capturing page titles accurately for timeonsite tracker in a single-page Angular app is challenging when navigating to other pages

Implemented the timeonsite JS tracker in my Angular web application using HTML tags as shown below, <script type="text/javascript"> var Tos; (function(d, s, id, file) { var js, fjs = d.getElementsByTagName(s)[0]; if (d.getElementByI ...

"The `ngClass` directive allows for applying classes as an `object` rather than just a simple `class` value

When applying the class name like this: <tr *ngIf="crud.isCreate" [ngClass]="{'create' : crud?.isCreate}"> The class name is not being added correctly. In HTML, it appears as: <tr _ngcontent-yql-c9="" ng-reflect-ng-class="[object Obje ...

Utilize toggle functionality for page rotation with rxjs in Angular framework

Managing a project that involves a container holding multiple cards across different pages can be overwhelming. To address this, the screen automatically rotates to the next page after a set time interval or when the user presses the space bar. To enhance ...

One way in Angular to set a validator pattern regex that matches either one rule or the other, but

Trying to implement user range matching with angular validators, like shown in the image below: https://i.stack.imgur.com/zXHn3.png The goal is to validate against one of two range options using an angular pattern validator: 1-99 or 1,2,5,6,8, but not b ...

What is the Typescript definition of a module that acts as a function and includes namespaces?

I'm currently working on creating a *.d.ts file for the react-grid-layout library. The library's index.js file reveals that it exports a function - ReactGridLayout, which is a subclass of React.Component: // react-grid-layout/index.js module.exp ...

Angular2 ngIf directive issue after initial button click

I have recently started using the Angular2 Framework, so please bear with me if I make any common mistakes. I have set up two forms in separate div tags: one for logging in and another for password reset. Below the login form, there is a link that, when cl ...

Convert your socket.io syntax to TypeScript by using the `import` statement instead

const io = require('socket.io')(server, { cors: { origin: '*', } }); Is there a way to convert this code to TypeScript using the syntax import {} from ''; ...

Exploring the functionalities of R.pick in TypeScript

Recently, I attempted the following code snippet: import R from 'ramda' import fs from 'fs' import path from 'path' import {promisify} from 'util' const readFile = promisify(fs.readFile) export async function disc ...

TypeScript conditional return type: effective for single condition but not for multiple conditions

In my code, I have implemented a factory function that generates shapes based on a discriminated union of shape arguments. Here is an example: interface CircleArgs { type: "circle", radius: number }; interface SquareArgs { type: "square" ...

Reducing SCSS import path in Angular 7

Creating a component that is deeply nested raises the issue of importing shared .scss files with long paths: @import '../../../app.shared.scss'; This hassle doesn't exist when it comes to .ts files, thanks to the configuration in tsconfig. ...

Guide on loading HTML templates into tab content within an Angular application

I am currently working on a project using Angular 8. After reading an informative article, I gained an understanding of concepts like ContentChildern, QueryList, and successfully built a sample tabs component. Here is the link to the article for reference ...

Typescript: Deciphering how to interpret a string with a mix of characters and numbers

Is there a way in TypeScript to add 40 to a variable of type string | number, and return a result as a string | number? My initial approach was to parse the variable to a number, then perform the addition, but how can I ensure that the variable is proper ...

The HTML canvas drawImage method overlays images when the source is modified

Trying to implement a scroll animation on my website, I came across a guide for creating an "Apple-like animation" using image sequences. Even though I'm new to Angular, I attempted to adapt the code to work with Angular. However, instead of animatin ...

Running cy.task after all test suites can be done by adding the task in a

I need some guidance on running cy.task after executing all test suites. I have a file generated at the start of the tests that I would like to remove once they are completed. Regardless of whether any tests passed or failed, I want to trigger cy.task im ...

The latest version of npm Boostrap (4.1.0) is missing some important CSS properties for the `background` tag

I am currently working on an Angular 5.2.10 project that utilizes angular-cli and bootstrap version: 4.0.0-beta.2 with a specific css class called .en-icon-24: .en-icon-24 { background: url(../../../../assets/img/icons.png) -370px 0px; width: 24 ...