admin管理员组

文章数量:1429973

class test{
    name : string
    children : Map<string,string> =new Map()
    constructor(){
        this.name='KIANA'
        this.children.set('name','OTTO')
    }
}
var t = new test()
console.log(t)
console.log(JSON.stringify(t))

The result is:

test { children: Map { 'name' => 'OTTO' }, name: 'KIANA' }
{"children":{},"name":"KIANA"}

How can I get the whole data like:

{"children":{'name':'OTTO'},"name":"KIANA"}

or

{"children":['name':'OTTO'],"name":"KIANA"}

Or, does it has a simpler way to describe the relationship of 'key value' in JSON and TypeScript

class test{
    name : string
    children : Map<string,string> =new Map()
    constructor(){
        this.name='KIANA'
        this.children.set('name','OTTO')
    }
}
var t = new test()
console.log(t)
console.log(JSON.stringify(t))

The result is:

test { children: Map { 'name' => 'OTTO' }, name: 'KIANA' }
{"children":{},"name":"KIANA"}

How can I get the whole data like:

{"children":{'name':'OTTO'},"name":"KIANA"}

or

{"children":['name':'OTTO'],"name":"KIANA"}

Or, does it has a simpler way to describe the relationship of 'key value' in JSON and TypeScript

Share Improve this question edited Feb 8, 2020 at 13:53 johannchopin 14.9k11 gold badges63 silver badges122 bronze badges asked Feb 8, 2020 at 13:37 XILINGXILING 534 bronze badges 1
  • convert thr map to an object – Marco Bonelli Commented Feb 8, 2020 at 13:39
Add a ment  | 

1 Answer 1

Reset to default 7

Preface: Class names should start with an uppercase character, so I've changed test to Test in the below.

Since Map isn't stringify-able by default, you have at least three choices:

  1. Implement toJSON on your Test class and return an object with a replacement for children (probably an array of arrays), or

  2. Implement a subclass of Map that has toJSON and use that in Test

  3. Implement a replacer that you use with JSON.stringify that handles Map instances.

While #1 works, it means you have to edit your toJSON method every time you add or remove properties from Test, which seems like a maintenance issue:

class Test {
  name: string
  children: Map<string, string> = new Map()
  constructor() {
    this.name = 'KIANA'
    this.children.set('name', 'OTTO')
  }
  toJSON() {
    return {
      name: this.name,
      children: [...this.children.entries()]
    }
  }
}
var t = new Test()
console.log(JSON.stringify(t))

Live Example:

class Test {
  name/*: string*/
  children/*: Map<string, string>*/ = new Map()
  constructor() {
    this.name = 'KIANA'
    this.children.set('name', 'OTTO')
  }
  toJSON() {
    return {
      name: this.name,
      children: [...this.children.entries()]
    }
  }
}
var t = new Test()
console.log(JSON.stringify(t))

[...this.children.entries()] creates an array of [name, value] arrays for the map.

But I prefer #2, a JSON-patible Map:

class JSONAbleMap extends Map {
  toJSON() {
    return [...this.entries()]
  }
}

...which you then use in Test:

class Test {
  name: string
  children: Map<string, string> = new JSONAbleMap()
  constructor() {
    this.name = 'KIANA'
    this.children.set('name', 'OTTO')
  }
}
var t = new Test()
console.log(JSON.stringify(t))

Live Example:

class JSONAbleMap extends Map {
  toJSON() {
    return [...this.entries()]
  }
}

class Test {
  name/*: string*/
  children/*: Map<string, string>*/ = new JSONAbleMap()
  constructor() {
    this.name = 'KIANA'
    this.children.set('name', 'OTTO')
  }
}
var t = new Test()
console.log(JSON.stringify(t))

Or #3, a replacer function you use with JSON.stringify:

function mapAwareReplacer(key: string|Symbol, value: any): any {
    if (value instanceof Map && typeof value.toJSON !== "function") {
        return [...value.entries()]
    }
    return value
}

...which you use when calling JSON.stringify:

console.log(JSON.stringify(t, mapAwareReplacer))

Live Example:

function mapAwareReplacer(key, value) {
    if (value instanceof Map && typeof value.toJSON !== "function") {
        return [...value.entries()]
    }
    return value
}

class Test {
  name/*: string*/
  children/*: Map<string, string>*/ = new Map()
  constructor() {
    this.name = 'KIANA'
    this.children.set('name', 'OTTO')
  }
}
var t = new Test()
console.log(JSON.stringify(t, mapAwareReplacer))

本文标签: javascriptHow to stringify an object of the type MapStack Overflow