├── .gitignore ├── .prettierrc ├── .babelrc ├── example ├── package.json └── index.js ├── README.md ├── package.json └── src └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | /lib 2 | /example/package-lock.json 3 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "semi": false, 3 | "trailingComma": "all", 4 | "printWidth": 120 5 | } 6 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["@babel/preset-env", "@babel/preset-stage-1", "@babel/preset-react"] 3 | } 4 | -------------------------------------------------------------------------------- /example/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "react": "latest", 4 | "react-serialize": "latest" 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /example/index.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { serialize, deserialize } from "react-serialize" 3 | 4 | const input = ( 5 |
6 |

7 | Hello 8 |

9 |
10 | ) 11 | console.log("input", input) 12 | 13 | const json = serialize(input) 14 | console.log("json", json) 15 | 16 | const output = deserialize(json) 17 | console.log("output", output) 18 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 | # React Serialize 4 | 5 | serialize and deserialize React components to JSON 6 | 7 |
8 | 9 |
10 | 11 | ```js 12 | serialize( 13 |
14 |

15 | Hello 16 |

17 |
18 | ) 19 | ``` 20 | 21 |
22 | 23 | ```js 24 | deserialize({ 25 | type: "div", 26 | props: { 27 | children: { 28 | type: "h1", 29 | props: { 30 | align: "center", 31 | children: { type: "blink", props: { children: "Hello" } } 32 | } 33 | } 34 | } 35 | }) 36 | ``` 37 | 38 |
39 | 40 | ## Install 41 | 42 | ```sh 43 | npm i react-serialize 44 | ``` 45 | 46 | ## API 47 | 48 | See [src/index.js](src/index.js#L1). 49 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-serialize", 3 | "productName": "React Serialize", 4 | "description": "Serialize and deserialize React components to JSON", 5 | "keywords": [ 6 | "react", 7 | "serialization" 8 | ], 9 | "version": "0.2.1", 10 | "main": "lib", 11 | "esnext": "src", 12 | "files": [ 13 | "bin", 14 | "lib", 15 | "src" 16 | ], 17 | "scripts": { 18 | "build": "babel src -d lib", 19 | "watch": "babel src -d lib -w", 20 | "prepare": "npm run build" 21 | }, 22 | "devDependencies": { 23 | "@babel/cli": "^7.0.0-beta.44", 24 | "@babel/core": "^7.0.0-beta.44", 25 | "@babel/preset-env": "^7.0.0-beta.44", 26 | "@babel/preset-stage-1": "^7.0.0-beta.44", 27 | "@babel/preset-react": "^7.0.0-beta.44" 28 | }, 29 | "peerDependencies": { 30 | "react": ">14.0.0" 31 | }, 32 | "license": "MIT" 33 | } 34 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | 3 | /** 4 | * Serialize React element to JSON string 5 | * 6 | * @param {ReactNode} element 7 | * @returns {string} 8 | */ 9 | export function serialize(element) { 10 | const replacer = (key, value) => { 11 | switch (key) { 12 | case "_owner": 13 | case "_store": 14 | case "ref": 15 | case "key": 16 | return 17 | default: 18 | return value 19 | } 20 | } 21 | 22 | return JSON.stringify(element, replacer) 23 | } 24 | 25 | /** 26 | * Deserialize JSON string to React element 27 | * 28 | * @param {string|object} data 29 | * @param {object?} options 30 | * @param {object?} options.components 31 | * @param {function?} options.reviver 32 | * @returns {ReactNode} 33 | */ 34 | export function deserialize(data, options) { 35 | if (typeof data === "string") { 36 | data = JSON.parse(data) 37 | } 38 | if (data instanceof Object) { 39 | return deserializeElement(data, options) 40 | } 41 | throw new Error("Deserialization error: incorrect data type") 42 | } 43 | 44 | function deserializeElement(element, options = {}, key) { 45 | let { components = {}, reviver } = options 46 | 47 | if (typeof element !== "object") { 48 | return element 49 | } 50 | 51 | if (element === null) { 52 | return element 53 | } 54 | 55 | if (element instanceof Array) { 56 | return element.map((el, i) => deserializeElement(el, options, i)) 57 | } 58 | 59 | // Now element has following shape { type: string, props: object } 60 | 61 | let { type, props } = element 62 | 63 | if (typeof type !== "string") { 64 | throw new Error("Deserialization error: element type must be string") 65 | } 66 | 67 | type = components[type] || type.toLowerCase() 68 | 69 | if (props.children) { 70 | props = { ...props, children: deserializeElement(props.children, options) } 71 | } 72 | 73 | if (reviver) { 74 | ;({ type, props, key, components } = reviver(type, props, key, components)) 75 | } 76 | 77 | return React.createElement(type, { ...props, key }) 78 | } 79 | --------------------------------------------------------------------------------