ããã¯ããªã«ãããããŠæžãããã®ïŒ
JavaScriptã®Map
ãSet
ãJSON#stringify
ã§JSONæååã«ãããšãæãã¬çµæã«ãªã£ãã®ã§ãã®ããããã¡ãã£ãšã¡ã¢ããŠãããããªãšã
ãããªæãã§ããã
// Map test('apply JSON.stringify to Map', () => { const map = new Map([ ['one', 1], ['two', 2], ['three', 3], ]); expect(JSON.stringify(map)).toBe('{}'); }); // Set test('apply JSON.strinfigy to Set', () => { const set = new Set(['JavaScript', 'TypeScript', 'Node.js']); expect(JSON.stringify(set)).toBe('{}'); });
MapãšObjectãSetãšArray
æåã«æžããããã«ãMap
ãSet
ãJSONæååã«ããããšãããšãåèŠã§ã¯ã¡ãã£ãšé©ãïŒïŒïŒçµæã«ãªããŸãã
// Map test('apply JSON.stringify to Map', () => { const map = new Map([ ['one', 1], ['two', 2], ['three', 3], ]); expect(JSON.stringify(map)).toBe('{}'); }); // Set test('apply JSON.strinfigy to Set', () => { const set = new Set(['JavaScript', 'TypeScript', 'Node.js']); expect(JSON.stringify(set)).toBe('{}'); });
å€ããªã«ãå
¥ããã«{}
ã«ãªããŸãããâŠã
Map
ãŸãMap
ããèŠãŠãããŸãããã
ããããJSON#stringify
ã§ã®ã·ãªã¢ã©ã€ãºãJSON#parse
ã§ã®ããŒã¹ã«å¯Ÿå¿ããŠããªããããšMDNã®Map
ã®ããŒãžã«æžããŠãããŸããã
ã·ãªã¢ã©ã€ãºã解éã®ããã®ãã€ãã£ããªå¯Ÿå¿ã¯ãããŸããã
ïŒãã ãã replacer åŒæ°ã§ JSON.stringify() ã䜿çšãã reviver åŒæ°ã§ JSON.parse() ã䜿çšããããšã§ã Map ã®ããã«ãç¬èªã®ã·ãªã¢ã©ã€ãºãšè§£éã®å¯Ÿå¿ãäœæããããšãã§ããŸãã Stack Overflow ã®è³ªå How do you JSON.stringify an ES6 Map? ãåç §ããŠãã ãããïŒ
Map / 解説 / Object ãš Map ã®æ¯èŒ
Map
ã®ã·ãªã¢ã©ã€ãºã«ã€ããŠã¯JSON#stringify
ã®replacer
åŒæ°ãããŒã¹ã«ã¯JSON#parse
ã®reviver
åŒæ°ã䜿ããšè¯ãããšæžãããŠ
ããã®ã§ãããããå°ãæ段ãããããã§ãã
Object#fromEntries
ã䜿ã£ãŠã1床Object
ã«å€æããã°ããã¿ããã§ããObject#fromEntries
ã¯ãiterableãªãªããžã§ã¯ããããŒãšå€ã®
ãã¢ãããªãé
åããªããžã§ã¯ãã«å€æããŸãã
Map
ã¯iterableã§ãã
Object.fromEntries() - JavaScript | MDN
ãšãããããã®çšéãã®ãã®ãæžããŠããŸããã
Object.fromEntries() / äŸ / Map ãã Object ãžã®å€æ
Object
ã«å€æããåŸã§ããã°ãJSON#stringify
ã§JSONæååã«ã§ããŸããâŠåœããåãšããã°ãåœããåã§ããã
JSON#parse
ã®æã¯ã©ããããããããšãããšãObject#entries
ã§ãªããžã§ã¯ããããŒãšå€ã®ãã¢ã®é
åã«å€æããŸãã
Object.entries() - JavaScript | MDN
ãã¡ããããã®çšéãã®ãã®ãæžããŠããŸãã
Object.entries() / äŸ / Object ãã Map ãžã®å€æ
ããããã°ãããšã¯Map
ã®ã³ã³ã¹ãã©ã¯ã¿ãŒã«æž¡ãã°Map
ãšããŠæ§æã§ããŸãã
Map() コンストラクター - JavaScript | MDN
Object
ã1床çµç±ããããšã§ãMap
ãšJSONæååã®å€æãè¡ãããšã«ãªããŸãã
åèïŒ
- Map<K, V> / Mapã¯çŽæ¥JSONã«ã§ããªã
- Map<K, V> / ä»ã®åãšã®çžäºéçš
Set
Set
ã«ã¯ã·ãªã¢ã©ã€ãºã«ã€ããŠã¯ç¹ã«æžãããŠããŸããã
ã§ãããçå±ã¯Map
ãšäŒŒããããªãã®ã§ãSet
ã«ã€ããŠã¯1床Array
ãéã«æãã°ããããã§ãã
Set
ã¯iterableã§ãããã³ã³ã¹ãã©ã¯ã¿ãŒã§é
åãåãåã£ãŠé
åããSet
ã«å€æããããšãã§ããŸãã
Set() コンストラクター - JavaScript | MDN
Set
ããé
åãžã®å€æã¯ãã¹ãã¬ããæŒç®åã䜿ããšç°¡åããã§ããã
åèïŒ
- Set
å·éã«èãããšMap
ãSet
ãJSONã®è¡šçŸã®ç¯å²å€ãªã®ã§çŽæ¥å€æããããšããŠãã ãªãªã®ã¯ããã§ãããéã«JSONã§è¡šçŸå¯èœãªãã®ã
æãã°ããããã§ããŸãããããšããæããªã®ã§ããã
ç¹ã«Map
ãJSON#stringify
ã§å€æã§ããªãã®ã¯ããªã«ãèããªãç¶æ
ã§èŠããšå²ãšé©ãæ°ãããŸãã
ãšããããã§ãç°¡åã«è©ŠããŠã¿ãŸããNode.jsïŒTypeScriptã®ç°å¢ã§ç¢ºèªããããšã«ããŸãã
ç°å¢
ä»åã®ç°å¢ã¯ããã¡ãã
$ node --version v18.15.0 $ npm --version 9.5.0
Node.jsãããžã§ã¯ããäœæãã
Node.jsãããžã§ã¯ããäœæããŸããäžç·ã«TypeScriptããã¹ãã³ãŒãã§ã®ç¢ºèªãšããããšã§Jestãã€ã³ã¹ããŒã«ã
$ npm init -y $ npm i -D typescript $ npm i -D @types/node@v18 $ npm i -D prettier $ npm i -D jest @types/jest $ npm i -D esbuild esbuild-jest $ mkdir test
äŸåé¢ä¿ã
"devDependencies": { "@types/jest": "^29.5.0", "@types/node": "^18.15.5", "esbuild": "^0.17.12", "esbuild-jest": "^0.5.0", "jest": "^29.5.0", "prettier": "^2.8.6", "typescript": "^5.0.2" }
scripts
ã
"scripts": { "build": "tsc --project .", "build:watch": "tsc --project . --watch", "typecheck": "tsc --project ./tsconfig.typecheck.json", "typecheck:watch": "tsc --project ./tsconfig.typecheck.json --watch", "test": "jest", "format": "prettier --write src test" },
èšå®ãã¡ã€ã«ã
tsconfig.json
{ "compilerOptions": { "target": "esnext", "module": "commonjs", "moduleResolution": "node", "lib": ["esnext"], "baseUrl": "./src", "outDir": "dist", "strict": true, "forceConsistentCasingInFileNames": true, "noFallthroughCasesInSwitch": true, "noImplicitOverride": true, "noImplicitReturns": true, "noPropertyAccessFromIndexSignature": true, "esModuleInterop": true }, "include": [ "src" ] }
tsconfig.typecheck.json
{ "extends": "./tsconfig", "compilerOptions": { "baseUrl": "./", "noEmit": true }, "include": [ "src", "test" ] }
.prettierrc.json
{ "singleQuote": true, "printWidth": 120 }
jest.config.js
module.exports = { testEnvironment: 'node', transform: { "^.+\\.tsx?$": "esbuild-jest" } };
ãã®ç°å¢ã§è©ŠããŠãããŸãããã
Map
ãŸãã¯Map
ããã
ãã®ãŸãŸJSON#stringifyãJSON#parse
æåã¯ãªã«ãèããã«Map
ãJSON#stringify
ã§JSONæååã«å€æããŠã¿ãŸããããã¯æåã«èŠãŸãããã{}
ã«ãªããŸãã
test('apply JSON.stringify to Map', () => { const map = new Map([ ['one', 1], ['two', 2], ['three', 3], ]); expect(JSON.stringify(map)).toBe('{}'); });
ãŸããJSON#parse
ã§ã ãªã€ãªMap
ã«ãã£ã¹ããããšããã§ãå®äœã¯ãªããžã§ã¯ããªã®ã§Map
ã®ã€ã³ã¹ã¿ã³ã¹ã§ã¯ãããŸããã
test('parse JSON as Map with JSON.parse', () => { const map = JSON.parse('{"one":1,"two":2,"three":3}') as Map<string, number>; expect(map).toEqual({ one: 1, two: 2, three: 3 }); expect(map).not.toBeInstanceOf(Map); expect(() => map.has('one')).toThrow(new TypeError('map.has is not a function')); });
Map
ã®ã¡ãœããã䜿ã£ããšããã§ãäŸå€ãã¹ããŒãããŸãã
Object#fromEntriesïŒJSON#stringifyãJSON#parseïŒObject#entriesïŒMapã³ã³ã¹ãã©ã¯ã¿ãŒ
次ã¯ãMap
ãšJSONæååã®å€æã®éã«ãObject#fromEntries
ãObject#entries
ãæãã§ã¿ãŸãã
Map
ããJSONæååãžã®å€æã
test('apply JSON.stringify to Object.fromEntries(Map)', () => { const map = new Map([ ['one', 1], ['two', 2], ['three', 3], ]); expect(JSON.stringify(Object.fromEntries(map))).toBe('{"one":1,"two":2,"three":3}'); });
JSON#stringify
ã®åã«ãMap
ãObject#fromEntries
ã§ãªããžã§ã¯ãã«å€æããããšã§JSONæååã«ã·ãªã¢ã©ã€ãºã§ããŸããã
次ã¯JSONæååããMap
ãžã®å€æã
test('parse JSON as Object with JSON.parse, convert to Map', () => { const map = new Map<string, number>(Object.entries(JSON.parse('{"one":1,"two":2,"three":3}'))); expect(map).toEqual( new Map([ ['one', 1], ['two', 2], ['three', 3], ]) ); expect(map).toBeInstanceOf(Map); });
ããã§ã¯ãJSON#parse
ã®çµæïŒãªããžã§ã¯ãïŒãObject#entries
ã§ããŒãšå€ã®ãã¢ã®é
åã«å€æããŠãããããMap
ã«åæ§æããŠ
ããŸãã
ããã§ãMap
ãJSONæååã«å€æãããããã®éãã§ããããã«ãªããŸããã
Set
ç¶ããŠã¯Set
ã
ãã®ãŸãŸJSON#stringifyãJSON#parse
ãã¡ãããæåã¯ãªã«ãèããã«Map
ãJSON#stringify
ã§JSONæååã«å€æããŠã¿ãŸãããã¡ãã{}
ã«ãªããŸãã
test('apply JSON.strinfigy to Set', () => { const set = new Set(['JavaScript', 'TypeScript', 'Node.js']); expect(JSON.stringify(set)).toBe('{}'); });
ãŸãJSON#parse
ã§ã ãªã€ãªSet
ã«ãã£ã¹ããããšããã§ãå®äœã¯é
åãªã®ã§Set
ã®ã€ã³ã¹ã¿ã³ã¹ãšããŠã¯æ±ãããŸããã
test('parse JSON as Set with JSON.parse', () => { const set = JSON.parse('["JavaScript","TypeScript","Node.js"]') as Set<string>; expect(set).toEqual(['JavaScript', 'TypeScript', 'Node.js']); expect(set).not.toBeInstanceOf(Set); expect(set).toBeInstanceOf(Array); expect(() => set.has('JavaScript')).toThrow(new TypeError('set.has is not a function')); });
é åå€æïŒJSON#stringifyãJSON#parseïŒSetã³ã³ã¹ãã©ã¯ã¿ãŒ
ã§ã¯ãSet
ãšJSONæååã®éã«1床æ瀺çã«é
åãžã®å€æãæãããšã§ããããã®åé¡ã解æ¶ããããšæããŸãã
ãŸãã¯JSON#stringify
ã®åã«ãã¹ãã¬ããæŒç®åãšçµã¿åãããŠSet
ãé
åã«å€æã
test('convert Set to Array, apply JSON.strinfigy', () => { const set = new Set(['JavaScript', 'TypeScript', 'Node.js']); expect(JSON.stringify([...set])).toBe('["JavaScript","TypeScript","Node.js"]'); });
é åãJSONæååã«ããŠããã®ã§ãé åã®JSONæååè¡šçŸã«ãªããŸãããã
JSON#parse
ã®å Žåã¯ãé
åãSet
ã«å€æããã°ããã®ã§ããã®ãŸãŸSet
ã®ã³ã³ã¹ãã©ã¯ã¿ãŒã«æž¡ããŸãã
test('parse JSON as Array with JSON.parse, convert to Set', () => { const set = new Set<string>(JSON.parse('["JavaScript","TypeScript","Node.js"]')); expect(set).toEqual(new Set(['JavaScript', 'TypeScript', 'Node.js'])); expect(set).toBeInstanceOf(Set); expect(set).not.toBeInstanceOf(Array); });
ããã§ãé
åãçµç±ããŠJSONæååãSet
ã«å€æã§ããŸããã
ããå°ã
æåã«Map
ã®ããã¥ã¡ã³ãã§ã·ãªã¢ã©ã€ãºã«ã€ããŠèŠãæã以äžã®ãããªèšè¿°ããããŸããã
ã·ãªã¢ã©ã€ãºã解éã®ããã®ãã€ãã£ããªå¯Ÿå¿ã¯ãããŸããã
ïŒãã ãã replacer åŒæ°ã§ JSON.stringify() ã䜿çšãã reviver åŒæ°ã§ JSON.parse() ã䜿çšããããšã§ã Map ã®ããã«ãç¬èªã®ã·ãªã¢ã©ã€ãºãšè§£éã®å¯Ÿå¿ãäœæããããšãã§ããŸãã Stack Overflow ã®è³ªå How do you JSON.stringify an ES6 Map? ãåç §ããŠãã ãããïŒ
Map / 解説 / Object ãš Map ã®æ¯èŒ
ããã§æžãããŠããStack Overflowã®è³ªåã¯ã以äžã«ãªããŸãã
javascript - How do you JSON.stringify an ES6 Map? - Stack Overflow
ãããã以äžã®ãããªé¢æ°ãäœæããã·ãªã¢ã©ã€ãºãããŒã¹åŠçãã«ã¹ã¿ãã€ãºããããšãã話ã§ãã
// JSON#stringifyã§äœ¿ã function replacer(key, value) { if(value instanceof Map) { return { dataType: 'Map', value: Array.from(value.entries()), // or with spread: value: [...value] }; } else { return value; } } // JSON#parseã§äœ¿ã function reviver(key, value) { if(typeof value === 'object' && value !== null) { if (value.dataType === 'Map') { return new Map(value.value); } } return value; }
ãã®é¢æ°ã䜿ã£ãŠMap
ãã·ãªã¢ã©ã€ãºãããšã以äžã®ããã«åæ
å ±ãåã蟌ãã 圢ã«ãªããŸãã
{ "dataType": "Map", "value": [[key, value],[key,value],...] }
ããŒã¹ã®æã«ã¯ããã®åæ
å ±ãèŠãŠMap
ã«æ»ãããšããããã§ããã
JSON#stringify
ã«ãããreplacer
é¢æ°ã¯ãªãã·ã§ã³ã®åŒæ°ã§ãJSONæååã«å€æããéã®æåãã«ã¹ã¿ãã€ãºã§ããŸãã
JSON.stringify() - JavaScript | MDN
JSON#parse
ã«ãããreviver
é¢æ°ãåãããªãã·ã§ã³ã®åŒæ°ã§ãJSONæååãããªããžã§ã¯ãã«å€æããéã®åŠçãã«ã¹ã¿ãã€ãº
ã§ããŸãã
JSON.parse() - JavaScript | MDN
ãã®ãããã䜿ããªããŠããå
ã»ã©ãŸã§ã«æžããObject#fromEntries
ãªã©ã䜿ãã°ããã®ã§ã¯ïŒãšããæ°ãããŸãããããšãã°
JSONæåååãã察象ã®ãªããžã§ã¯ãã®ããããã£ã«Map
ããã£ãããããšãObject#fromEntries
ã§ã¯ããŸããããŸããã
ããã§å¹æãããã®ã¯ããããã¬ãã«ã®ãªããžã§ã¯ããMap
ã ã£ãå Žåã§ããããã
ãšããããã§ãä»åã¯Map
ã§ç°¡åã«è©Šãããšã«ããŸãã
ãŸãã¯JSON#stringfy
ïŒreplacer
é¢æ°ã
test('apply JSON.stringify to Object include Map', () => { const book = { isbn: '978-4873119700', title: 'JavaScript 第7ç', price: 5060, tags: new Map([ ['language', 'JavaScript'], ['category', 'Programming'], ]), }; expect(JSON.stringify(book)).toBe('{"isbn":"978-4873119700","title":"JavaScript 第7ç","price":5060,"tags":{}}'); const replacer = (key: any, value: any) => { if (value instanceof Map) { return Object.fromEntries(value); } return value; }; expect(JSON.stringify(book, replacer)).toBe( '{"isbn":"978-4873119700","title":"JavaScript 第7ç","price":5060,"tags":{"language":"JavaScript","category":"Programming"}}' ); });
ãããªæãã§ãMap
ãããããã£ã«æã€ãªããžã§ã¯ãã§ãåé¡ãªãJSONæååã«ã§ããŸãããä»åã¯ãåæ
å ±ãJSONã«åã蟌ãããšã¯
ããŠããŸããã
次ã¯JSON#parse
ïŒreviver
é¢æ°ã
test('parse JSON as Object with JSON.parse, convert to Object include Map', () => { const bookString = '{"isbn":"978-4873119700","title":"JavaScript 第7ç","price":5060,"tags":{"language":"JavaScript","category":"Programming"}}'; const bookAsObject = JSON.parse(bookString); expect(bookAsObject.tags).not.toBeInstanceOf(Map); expect(bookAsObject).not.toEqual({ isbn: '978-4873119700', title: 'JavaScript 第7ç', price: 5060, tags: new Map([ ['language', 'JavaScript'], ['category', 'Programming'], ]), }); expect(bookAsObject).toEqual({ isbn: '978-4873119700', title: 'JavaScript 第7ç', price: 5060, tags: { language: 'JavaScript', category: 'Programming', }, }); const revivier = (key: any, value: any) => { if (key === 'tags') { return new Map(Object.entries(value)); } return value; }; const book = JSON.parse(bookString, revivier); expect(book).toEqual({ isbn: '978-4873119700', title: 'JavaScript 第7ç', price: 5060, tags: new Map([ ['language', 'JavaScript'], ['category', 'Programming'], ]), }); expect(book.tags).toBeInstanceOf(Map); });
ãã®äŸã§ã¯åæ
å ±ããªãã®ã§ãããããã£åã§æ±ºãæã¡ã§Map
ã«å€æããããã«ããŠããŸãã
ã¡ãªã¿ã«ããããŸã§æžããšãªããšãªãæ°ã¥ãã®ã§ããããããã¬ãã«ã®ãªããžã§ã¯ããMap
ã§ãã£ãŠãreplacer
é¢æ°ã§ã·ãªã¢ã©ã€ãºã
reviver
é¢æ°ã§ããŒã¹ããããšãã§ããŸãã
ãããªæãã§ããã
## JSON#stringifyïŒreplacer test('apply JSON.stringify with replacer to Object include Map', () => { const map = new Map([ ['one', 1], ['two', 2], ['three', 3], ]); const replacer = (key: any, value: any) => { if (value instanceof Map) { expect(key).toBe(''); return Object.fromEntries(value); } return value; }; expect(JSON.stringify(map, replacer)).toBe('{"one":1,"two":2,"three":3}'); }); ## JSON#parseïŒreviver test('parse JSON as Map with JSON.parse with revivier', () => { const mapAsString = '{"one":1,"two":2,"three":3}'; const revivier = (key: any, value: any) => { if (key === '') { return new Map(Object.entries(value)); } return value; }; const map = JSON.parse(mapAsString, revivier); expect(map).toEqual( new Map([ ['one', 1], ['two', 2], ['three', 3], ]) ); expect(map).toBeInstanceOf(Map); });
ãŸããæéãå¢ããã ããªã®ã§ãããªãã§ããããã©ãâŠã
ããŒããªãå Žåã¯ã空æååãæž¡ãããããã§ããã
ä»åã¯ããããªãšããã§ã
ãŸãšã
Map
ãSet
ãJSONæååã«ã·ãªã¢ã©ã€ãºãããŒã¹ããããšããŠããã£ãã®ã§ãã¡ãã£ãšãŸãšããŠãããŸããã
察å¿æ¹æ³ã¯ããã£ãã®ã§ããããã¹ãããããããã£ã«Map
ãSet
ãããããããšåä»ãªããšã«ãªãã®ã§ãJSONã«å€æãããªããžã§ã¯ãã¯
çŽ çŽã«JSONã§è¡šçŸã§ããç¯å²ã«ãšã©ããæ¹ãïŒMap
ãSet
ãå«ããªãæ¹ãïŒããã®ããªãšæããŸããâŠã