Logan Wlv
Logan Wlv

Reputation: 3744

Typescript can not read a map<string,string> from JSON data

I am using Angular5 on a spring boot application. I am trying to return a Map in JSON.

Spring :

//some method
return ResponseEntity.ok((new Gson()).toJson(/*My map object*/));

Angular5 :

sql_list = new Map<string,string>();
this.myService.getQueries().subscribe(
    data => {
        console.log("Received data: ");
        console.log(data);
        this.sql_list = data;
        console.log(this.sql_list.get("query1"));
    } 
);

In the client I can see that the data is well received using console.log :

Received data:
{
  "query1" : "select * from test",
  "query2" : "select * from test2",
  "query3" : "select * from test3"
}

But sql_list object gives me that error when trying to use map.get(string key) method :

ERROR TypeError: _this.sql_list.get is not a function

Which mistake did I do there?

EDIT: following Florian answer this is working:

this.sql_list = new Map<string, string>(Object.entries(data));

Upvotes: 1

Views: 3032

Answers (3)

Nenad Jovicic
Nenad Jovicic

Reputation: 185

As Florian explained, you are assigning plane JSON object to something that should be Map One thing that you can do if you really want it to be Map is to do

for (const key in data) {
    this.sql_list.set(key, data[key]);
}

This will loop through all keys you have ('query1', 'query2', 'query3') and then it will set value of that key in your map

Just wondering why are you using Map, because if you already know how your object will look like, and which fields it will have, why don't you just make a class and type it as that class?

Just a suggestion. Also easier when you write code in VS Code for example, you will have autocomplete

Upvotes: 4

ShamPooSham
ShamPooSham

Reputation: 2379

When you do this.sql_list = data, you overwrite whatever sql_list was before, so it's no longer a Map<string, string>. Because data is a plain javascript object, that's what sql_list will be as well.

There aren't many cases where you need to use Map<string, string> instead of plain objects, because you can access object values by indexing like this: sql_list['query1']. to make this possible in typescript, you have to declare sql_list as an any type, or create your own type, for example a string mapper type like this:

interface strMap {
  [key: string]: string;
}

then you just declare sql_list: strMap;.

If you still have a good reason to use Map<string, string>, you can look at this question

Upvotes: 2

Florian Albrecht
Florian Albrecht

Reputation: 2326

In your first line, you create a Map:

sql_list = new Map<string,string>();

But later on, in the data handler, you just overwrite that object with the received data:

this.sql_list = data;

As data is something returned by the HTTP handler, it will most likely not fulfill the Map interface and not offer functions like get. Instead, it will be a plain JavaScript object which you could read like console.log(sql_list['query1']).

You could use some clever combination of Object.keys() and set() (of your empty Map object stored in sql_list) to "convert" the returned JavaScript object data into a full Map object.

Upvotes: 3

Related Questions