Gatsby: How to parse specific JSON files using gatsby-transformer-json?

Created on 10 Oct 2018  路  2Comments  路  Source: gatsbyjs/gatsby

Summary

I have a file structure that looks like this:

conferences/
  en.json
  ar.json

meetups/
  en.json
  ar.json

I want to be able to use either the filesystem source or the JSON transformer plugin to load a specific JSON file. e.g. In a certain case I only want to load conferences/en.json.

Relevant information

I've tried using the GraphQL API but I could never get it to load a specific JSON file no matter how I tried, I could only filter on nodes within the JSON files, but not the files themselves. The filesystem source plugin allowed me to filter to only get the specific files I want, but I wasn't able to get their contents through it. The only approach I was able to get to work is to use the filesystem source plugin with this GraphQL query

{
  allFile(filter: {name: {eq: "en"}, relativeDirectory: {eq: "conferences"}}) {
    edges {
      node {
        publicURL
      }
    }
  }
}

and then fetching the JSON and parsing it myself:

let readJSON = (url) => {
  console.log(url);
  let response = await fetch(url);
  let json = await response.json();
  return json;
}

const ConferencesPage = ({data}) => (
  <Layout>
    <ul>
      {data.allFile.edges.map((elem) =>
        <li>
          {console.log(elem)}
          <Conference conference={readJSON(elem.node.publicURL)} key={i} />
        </li>
      )}
    </ul>
    <h1>Hi from conferences</h1>
    <p>Welcome to page 2</p>
    <Link to="/">Go back to the homepage</Link>
  </Layout>
)

Am I thinking about this the wrong way? Is there perhaps another plugin that can read file contents that I can utilize instead of all the solutions I tried?

Most helpful comment

Hey @obahareth,
I've played around with this and the best approach I found was using both plugins and the allFile query. Here's how I got it working:

I recreated your directory structure:

conferences/
  en.json
  ar.json

meetups/
  en.json
  ar.json

Adding a simple json object to each file:

{
  "name": "Omar"
}

I installed both plugins:

npm install --save gatsby-transformer-json gatsby-source-filesystem

and updated the plugin settings in gatsby-config.js:

module.exports = {
  siteMetadata: {
    title: 'Gatsby Default Starter',
  },
  plugins: [
    'gatsby-plugin-react-helmet',
    {
      resolve: `gatsby-plugin-manifest`,
      options: {
        name: 'gatsby-starter-default',
        short_name: 'starter',
        start_url: '/',
        background_color: '#663399',
        theme_color: '#663399',
        display: 'minimal-ui',
        icon: 'src/images/gatsby-icon.png', // This path is relative to the root of the site.
      },
    },
    `gatsby-transformer-json`,
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `meetups`,
        path: `${__dirname}/src/meetups`,
      },
    },
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `conferences`,
        path: `${__dirname}/src/conferences`,
      }
    },
    'gatsby-plugin-offline'
  ]
}

I then filtered the allFile query and requested the return of childConferenceJson, which will be contents of ./src/conferences/en.json:

{
  allFile (filter: { 
    name: { eq : "en" } 
    sourceInstanceName: { eq : "conferences" }
  }) {
    edges {
      node {
        childConferencesJson {
          name
        }
      }
    }
  }
}

This returns me:

{
  "data": {
    "allFile": {
      "edges": [
        {
          "node": {
            "childConferencesJson": {
              "name": "Omar"
            }
          }
        }
      ]
    }
  }
}

I hope that helps!
If you run into any problems, try deleting your .cache directory before running gatsby develop.

All 2 comments

Hey @obahareth,
I've played around with this and the best approach I found was using both plugins and the allFile query. Here's how I got it working:

I recreated your directory structure:

conferences/
  en.json
  ar.json

meetups/
  en.json
  ar.json

Adding a simple json object to each file:

{
  "name": "Omar"
}

I installed both plugins:

npm install --save gatsby-transformer-json gatsby-source-filesystem

and updated the plugin settings in gatsby-config.js:

module.exports = {
  siteMetadata: {
    title: 'Gatsby Default Starter',
  },
  plugins: [
    'gatsby-plugin-react-helmet',
    {
      resolve: `gatsby-plugin-manifest`,
      options: {
        name: 'gatsby-starter-default',
        short_name: 'starter',
        start_url: '/',
        background_color: '#663399',
        theme_color: '#663399',
        display: 'minimal-ui',
        icon: 'src/images/gatsby-icon.png', // This path is relative to the root of the site.
      },
    },
    `gatsby-transformer-json`,
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `meetups`,
        path: `${__dirname}/src/meetups`,
      },
    },
    {
      resolve: `gatsby-source-filesystem`,
      options: {
        name: `conferences`,
        path: `${__dirname}/src/conferences`,
      }
    },
    'gatsby-plugin-offline'
  ]
}

I then filtered the allFile query and requested the return of childConferenceJson, which will be contents of ./src/conferences/en.json:

{
  allFile (filter: { 
    name: { eq : "en" } 
    sourceInstanceName: { eq : "conferences" }
  }) {
    edges {
      node {
        childConferencesJson {
          name
        }
      }
    }
  }
}

This returns me:

{
  "data": {
    "allFile": {
      "edges": [
        {
          "node": {
            "childConferencesJson": {
              "name": "Omar"
            }
          }
        }
      ]
    }
  }
}

I hope that helps!
If you run into any problems, try deleting your .cache directory before running gatsby develop.

That's a huge help and it worked out great for me, thanks so much @dakebl!

Was this page helpful?
0 / 5 - 0 ratings