【问题标题】:Node JS [Object Map] while writing object to file将对象写入文件时的节点JS [对象映射]
【发布时间】:2018-09-03 12:31:16
【问题描述】:

我在 stackoverflow 和其他教程网站上阅读了许多关于将对象/JSON 写入文件的帖子,但没有一个解决方案适合我。

1) 代码:

let messages = await fetchMessages()
console.log(messages)    // Prints an object
fs.writeFileSync('./msgdata.json', messages , 'utf-8'); 

2) 也试过了,

fs.writeFileSync('./msgdata.json', JSON.stringify(messages) , 'utf-8'); 

3) 也试过了,

fs.writeFile(),但得到与上面相同的输出。

msgdata.json:(对于 1)

[object Map]

msgdata.json:(对于 2 和 3)

{}

有人能指出造成这种情况的原因吗?

## console.log(messages) 的输出##

OUTPUT contains 10 more such objects having different id's:

channel:
   TextChannel {
     type: 'text',
     id: '424825532274253312',
     name: 'request',
     position: 69,
     parentID: '397363224286473987',
     permissionOverwrites: [Object],
     topic: null,
     nsfw: false,
     lastMessageID: '427143105410760704',
     guild: [Object],
     messages: [Object],
     _typing: Map {} },
  id: '427142596817846272',
  type: 'DEFAULT',
  content: '**Select your emoji:** __***Group 9:***__',
  author:
   ClientUser {
     id: '407083773537350272',
     username: 'Bot',
     discriminator: '9256',
     avatar: '9c374e719ba2ab4e69fd577005b635bf',
     bot: true,
     lastMessageID: null,
     lastMessage: null,
     verified: true,
     email: null,
     localPresence: {},
     _typing: Map {},
     friends: Collection {},
     blocked: Collection {},
     notes: Collection {},
     premium: null,
     mfaEnabled: false,
     mobile: null,
     settings: [Object],
     guildSettings: Collection {} },
  member:
   GuildMember {
     guild: [Object],
     user: [Object],
     _roles: [Array],
     serverDeaf: false,
     serverMute: false,
     selfMute: undefined,
     selfDeaf: undefined,
     voiceSessionID: undefined,
     voiceChannelID: undefined,
     speaking: false,
     nickname: null,
     joinedTimestamp: 1517127343434,
     lastMessageID: null,
     lastMessage: null },
  pinned: false,
  tts: false,
  nonce: undefined,
  system: false,
  embeds: [],
  attachments: Collection {},
  createdTimestamp: 1521909131007,
  editedTimestamp: null,
  reactions:
   Collection {
     'taillow:417281639777959940' => [Object],
     'shroomish:417281639899463680' => [Object],
     'sableye:417281640197521419' => [Object],
     'ralts:417281642735075329' => [Object],
     'sentret:417281644001624076' => [Object],
     'shuppet:417281644291162132' => [Object],
     'torchic:417281647210397706' => [Object],
     'snubbull:417281647692480522' => [Object],
     'sunkern:417281647763783681' => [Object],
     'slowpoke:417281648653107200' => [Object],
     'teddiursa:417281649537974273' => [Object],
     'sneasel:417281649613471747' => [Object],
     'snorunt:417281649819123712' => [Object],
     'surskit:417281650163056640' => [Object],
     'qwilfish:417281654629859348' => [Object],
     'shelgon:417281654730522624' => [Object] },
  mentions:
   MessageMentions {
     everyone: false,
     users: Collection {},
     roles: Collection {},
     _content: '**Select your emoji:** __***Group
9:***__',
     _client: [Object],
     _guild: [Object],
     _members: null,
     _channels: null },
  webhookID: null,
  hit: null,
  _edits: [] },

【问题讨论】:

  • 您确定console.log(messages) 没有在控制台上记录{} 吗?
  • @vibhor1997a,是的,很确定

标签: javascript json node.js


【解决方案1】:

这是因为返回的对象是一个 Map 对象 (MDN)。当你 JSON.strigify 一个 Map 对象时,它总是返回 {}。有两种方法可以获得存储地图的可读 JSON。首先是遍历所有条目并创建一个 JSON(考虑键和值)。这应该很容易实现。

另一种方法是从 Map 创建一个数组,然后将其字符串化。

fs.writeFileSync('./msgdata.json', JSON.stringify([...myObject]) , 'utf-8'); 

【讨论】:

  • 感谢您的回答,我试试看这里更新
  • (node:4252) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): TypeError: Converting circular structure to JSON (node:4252) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code. 尝试了您的解决方案,我收到此错误...
  • @eNthUsiAst 您能否提及console.log(messages) 打印的内容?
  • 添加了@Shiven
  • @eNthUsiAst 好吧,哇。 [object Map] 似乎很奇怪,因为输出似乎是 JSON。但实际上,你能告诉我console.log(JSON.stringify(messages)) 打印的是什么而不是简单的日志吗?我相信它会是空的,是吗?
【解决方案2】:

您可以定义Map.prototype.toJSON 哪个有效,但它不是标准的,不鼓励使用。如果找到它,JSON.stringify 会自动调用它。

Map.prototype.toJSON = function() {return [...this];};
console.log(JSON.stringify(messages));

更好的方法是定义您自己的replacer 函数(如果您需要从 JSON 重建地图,也可以定义 reviver 函数)。这里我也将表示数组的地图包裹在一个特殊的对象中,以便在 JSON 中区分地图和普通数组:

function replacer (key, value) {
    if (value instanceof Map) {
        return {
            _type: "map",
            map: [...value],
        }
    } else return value;
}

function reviver (key, value) {
    if (value._type == "map") return new Map(value.map);
    else return value;
}

let str = JSON.stringify(messages, replacer);
let msg = JSON.parse(str, reviver);

您遇到的有关循环结构的错误意味着那里的某些对象/数组包含对其自身的引用。当您存储消息时,您不需要存储与频道等相关的所有信息,而只需存储 id。这意味着将replacer 扩展为TextChannels、ClientUsers、GuildMembers 等:

if (value instanceof TextChannel) {
  return {
    _type: "TextChannel",
    id: value.id,
  };
}

【讨论】:

  • 哇!这真是我学到的很酷的东西。 ...value 语法是什么?如果我使用第一种方法 Map.prototype.toJSON,那我该怎么称呼它?
  • JSON.stringify 将在地图上出现时调用 toJSON 方法。 [...value] 是一种扩展语法 (ES6+),会将 map 转换为数组 [[key, value], [key value],...]
  • 好的,谢谢理解...在尝试您的解决方案时遇到此错误... ``(node:4252) UnhandledPromiseRejectionWarning:未处理的承诺拒绝(拒绝 id:1):TypeError:将循环结构转换为 JSON (节点:4252)[DEP0018] DeprecationWarning:不推荐使用未处理的承诺拒绝。将来,未处理的承诺拒绝将使用非零退出代码终止 Node.js 进程。`尝试了您的解决方案,我收到此错误...`
  • 但是每个单独的消息类型是什么(channel: 之前的东西)?您需要一个替换器来替换“外来”类(正如我在编辑中所做的那样)或消息本身以用它们的 ID 替换“外来”类。
  • 我不确定我是否理解它,您是否可以编辑您的答案我应该如何实际操作? :(
【解决方案3】:
var util = require('util');
fs.writeFileSync('./data.json', util.inspect(obj) , 'utf-8');

参考。 Write objects into file with Node.js

【讨论】:

    猜你喜欢
    • 2017-06-27
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-09-19
    • 2019-03-30
    • 2021-05-20
    • 2018-05-30
    相关资源
    最近更新 更多