ค้นหาเว็บไซต์

javascript - วิธีการแปลงอ็อบเจ็กต์ของประเภท Map เป็นสตริง


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))

ผลลัพธ์คือ:

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

ฉันจะสามารถได้ข้อมูลทั้งหมดแบบนี้ได้อย่างไร:

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

หรือ

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

หรือว่ามันมีวิธีที่ง่ายกว่าที่จะอธิบายความสัมพันธ์ของ 'คีย์และค่า' ใน JSON และ TypeScript

คำตอบ #1

คำนำ: ชื่อคลาสควรเริ่มด้วยตัวอักษรใหญ่ ดังนั้นฉันจึงเปลี่ยน test เป็น Test ด้านล่างนี้

เนื่องจาก Map ไม่สามารถแปลงเป็นสตริงได้โดยค่าเริ่มต้น คุณมีตัวเลือกอย่างน้อยสามข้อ:

  1. ใช้งาน toJSON บนคลาส Test ของคุณและคืนค่าอ็อบเจ็กต์ที่มีตัวแทนสำหรับ children (น่าจะเป็นอาเรย์ของอาเรย์) หรือ

  2. สร้างซับคลาสของ Map ที่มี toJSON และใช้สิ่งนั้นใน Test

  3. สร้าง replacer ที่คุณใช้กับ JSON.stringify ที่จัดการกับอินสแตนซ์ Map.

แม้ว่าวิธี #1 จะใช้ได้ แต่ก็หมายความว่าคุณต้องแก้ไขเมธอด toJSON ของคุณทุกครั้งที่คุณเพิ่มหรือลบคุณสมบัติจาก Test ซึ่งดูเหมือนจะเป็นปัญหาในการบำรุงรักษา:

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))

ตัวอย่างสด:

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()] สร้างอาเรย์ของอาเรย์ [name, value] สำหรับแมป

แต่ฉันชอบ #2 ซึ่งเป็น Map ที่เข้ากันได้กับ JSON:

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

...ซึ่งคุณจะนำไปใช้ใน 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))

ตัวอย่างสด:

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))

หรือ #3 ฟังก์ชันแทนที่ที่คุณใช้กับ JSON.stringify:

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

...ซึ่งคุณใช้เมื่อเรียก JSON.stringify:

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

ตัวอย่างสด:

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))

บทความที่เกี่ยวข้อง