npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

json-jsx

v1.0.1

Published

JSX library for creating JSON.

Readme

json-jsx

A JSX library for creating JSON.

Contents

About

This repository provides a JSX pragma for writing JSON as component based code in the same way you might write HTML + JS with React.

This allows you to define elegant, re-usable and composable components for your JSON.

Usage

Getting Started

Install this package using npm / yarn.

yarn add json-jsx

The recommended way to use this package is with JSX in your codebase. This can be achieved by using the @babel/plugin-transform-react-jsx and babel-plugin-jsx-pragmatic plugins.

Add the babel plugins to your codebase:

yarn add -D @babel/plugin-transform-react-jsx babel-plugin-jsx-pragmatic

And update your .babelrc to use the JSX babel plugins:

{
  "plugins": [
    [
      "@babel/plugin-transform-react-jsx",
      {
        "pragma": "jsx",
        "pragmaFrag": "jsxFrag"
      }
    ],
    [
      "babel-plugin-jsx-pragmatic",
      {
        "module": "json-jsx",
        "import": "jsx",
        "export": "createObject"
      },
      "jsx"
    ],
    [
      "babel-plugin-jsx-pragmatic",
      {
        "module": "json-jsx",
        "import": "jsxFrag",
        "export": "Fragment"
      },
      "jsxFrag"
    ]
  ]
}

You can now use JSX and JSX Fragments <></> in your codebase and Babel will parse the JSX using the json-jsx pragmas.

See below for an example of various ways you can use this syntax.

const EslintExtensions = ({ children }) => ({ extends: children });
const EslintPlugins = ({ plugins }) => ({ plugins });

const CommonRules = () => (
  <>
    {{ "import/no-extraneous-dependencies": "error" }}
    {{ "no-console": "warn" }}
  </>
);

const ReactRules = () => ({
  "react/jsx-no-comment-textnodes": "error",
  "react/jsx-no-duplicate-props": "error",
});

const EslintRules = ({ isReact }) => (
  <rules>
    <CommonRules />
    {isReact && <ReactRules />}
  </rules>
);

const defaultPlugins = ["import", "jest", "prettier"];

const MyEslintrcConfig = ({ isReact = true }) => {
  const plugins = isReact ? [...defaultPlugins, "react"] : defaultPlugins;

  return (
    <eslintrc parser={"babel-eslint"}>
      <env es6={true} jest={true} node={true} />
      <EslintExtensions>
        {"eslint:recommended"}
        {"plugin:import/recommended"}
        {"plugin:jest/recommended"}
        {"prettier"}
      </EslintExtensions>
      <EslintPlugins plugins={plugins} />
      <EslintRules isReact={isReact} />
      <parserOptions>
        <ecmaFeatures jsx={true} />
      </parserOptions>
    </eslintrc>
  );
};

console.log(<MyEslintConfig />);
/**
 * {
 *    parser: "babel-eslint",
 *    env: { es6: true, jest: true, node: true },
 *    extends: [
 *      "eslint:recommended",
 *      "plugin:import/recommended",
 *      "plugin:jest/recommended",
 *      "prettier"
 *    ],
 *    plugins: [ "import", "react", "jest", "prettier" ],
 *    rules: {
 *      "import/no-extraneous-dependencies": "error",
 *      "no-console": "warn",
 *      "react/jsx-no-comment-textnodes": "error",
 *      "react/jsx-no-duplicate-props": "error"
 *    },
 *    parserOptions: { ecmaFeatures: { jsx: true } }
 *  }
 */

APIs

createObject

createObject is a JSX Pragma for creating JSON objects.

Using vanilla JS:

import { createObject, Fragment } from "json-jsx";

/**
 * Evaluates to:
 *
 * {
 *   "myProp": "myPropValue",
 *   "childComponentName": {}
 * }
 *
 * Note that the `componentName` is not assigned as it is
 * the top level component.
 */
const myObjectWithStringComponent = createObject(
  "componentName",
  { myProp: "myPropValue" },
  [createObject("childComponentName")]
);

/**
 * Evaluates to:
 *
 * {
 *   "myProp": "myPropValue",
 *   "plain": "json children",
 *   "are": "merged",
 *   "including": [{
 *     "array": "values"
 *   }]
 * }
 *
 */
const myObjectWithJsonChildren = createObject(
  "componentName",
  { myProp: "myPropValue" },
  [
    { plain: "json children" },
    { are: "merged", including: [{ array: "values" }] },
  ]
);

const MyFunctionalComponent = ({ children, ...props }) =>
  createObject("fnComponentName", props, children);

/**
 * Evaluates to:
 *
 * {
 *   "myFnProp": "myFnPropValue",
 *   "componentName": {
 *     "myProp": "myPropValue",
 *     "childComponentName": {}
 *   }
 * }
 *
 * Note that `componentName` is used here because it is a
 * child component to the `fnComponentName` component.
 */
const myObjectWithFunctionalComponent = createObject(
  MyFunctionalComponent,
  { myFnProp: "myFnPropValue" },
  [myObjectWithStringComponent]
);

/**
 * Fragments enable array-like constructions.
 */

/**
 * Used by themselves, sub-components are assigned to an
 * array.
 *
 * Evaluates to:
 *
 * [
 *   {
 *     "myProp": "myPropValue"
 *   },
 *   {
 *     "myProp": "myPropValue"
 *   }
 * ]
 */
const myArrayUsingFragments = createObject(
  Fragment,
  {},
  createObject("componentName", { myProp: "myPropValue" }),
  createObject("componentName", { myProp: "myPropValue" })
);

/**
 * Within the scope of an outer object, the Fragment acts
 * transparently, as if it were not there.
 *
 * Evaluates to:
 *
 * {
 *   "componentName1": {
 *     "myProp": "myPropValue"
 *   },
 *   "componentName2": {
 *     "myProp": "myPropValue"
 *   }
 * }
 */
const myObjectUsingFragments = createObject(
  "componentName",
  {},
  createObject(
    Fragment,
    {},
    createObject("componentName1", { myProp: "myPropValue" }),
    createObject("componentName2", { myProp: "myPropValue" })
  )
);

Equivalent using JSX:

/**
 * Evaluates to:
 *
 * {
 *   "myProp": "myPropValue",
 *   "childComponentName": {}
 * }
 *
 * Note that the `componentName` is not assigned as it is
 * the top level component.
 */
const myObjectWithStringComponent = (
  <componentName myProp={"myPropValue"}>
    <childComponentName />
  </componentName>
);

/**
 * Evaluates to:
 *
 * {
 *   "myProp": "myPropValue",
 *   "plain": "json children",
 *   "are": "merged",
 *   "including": [{
 *     "array": "values"
 *   }]
 * }
 *
 */
const myObjectWithJsonChildren = (
  <componentName myProp={"myPropValue"}>
    {{ plain: "json children" }}
    {{ are: "merged", including: [{ array: "values" }] }}
  </componentName>
);

const MyFunctionalComponent = ({ children, ...props }) => (
  <fnComponentName {...props}>{children}</fnComponentName>
);

/**
 * Evaluates to:
 *
 * {
 *   "myFnProp": "myFnPropValue",
 *   "componentName": {
 *     "myProp": "myPropValue",
 *     "childComponentName": {}
 *   }
 * }
 *
 * Note that `componentName` is used here because it is a
 * child component to the `fnComponentName` component.
 */
const myObjectWithFunctionalComponent = (
  <MyFunctionalComponent myFnProp={"myFnPropValue"}>
    {myObjectWithStringComponent}
  </MyFunctionalComponent>
);

/**
 * Fragments enable array-like constructions.
 */

/**
 * Used by themselves, sub-components are assigned to an
 * array.
 *
 * Evaluates to:
 *
 * [
 *   {
 *     "myProp": "myPropValue"
 *   },
 *   {
 *     "myProp": "myPropValue"
 *   }
 * ]
 */
const myArrayUsingFragments = (
  <>
    <componentName myProp={"myPropValue"} />
    <componentName myProp={"myPropValue"} />
  </>
);

/**
 * Within the scope of an outer object, the Fragment acts
 * transparently as if it were not there.
 *
 * Evaluates to:
 *
 * {
 *   "componentName1": {
 *     "myProp": "myPropValue"
 *   },
 *   "componentName2": {
 *     "myProp": "myPropValue"
 *   }
 * }
 */
const myObjectUsingFragments = (
  <componentName>
    <>
      <componentName1 myProp={"myPropValue"} />
      <componentName2 myProp={"myPropValue"} />
    </>
  </componentName>
);
Options

| Argument | Description | | -------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | type | A string name, functional component or Fragment. If a string is provided, the value is set as a key in the parent JSON object (unless this is the top level component, in which case the type is not used). If a functional component is provided, it is evaluated using the provided props and children. | | props | An object containing the properties that should be assigned against the type key in the JSON object. | | children | An array of objects. If the object is a plain JSON object, it will be merged into the object assigned against the type key. If the object is a component then it will be added to type object against a key of the component's name. |

Developing

Install

yarn install --frozen-lockfile

Build

yarn build

Test

yarn test

Lint

yarn lint

Contributing

Please check out the CONTRIBUTING docs.

Changelog

Please check out the CHANGELOG docs.

Roadmap

Please check out the ROADMAP docs.