Gatsby: [gatsby-transformer-json] access all json file in subdirectories within a folder

Created on 21 Jan 2020  路  8Comments  路  Source: gatsbyjs/gatsby

Description

I would like to access all transformed JSON within a folder, where each json file is located within a subdirectory and is named project.json. However, this only allows access via allProjectNameJson. I will not know the projectName (folder name) at runtime to add it to my query.

Steps to reproduce

CodeSandbox
I built this sandbox with the required gatsby-config.js entries for gatsby-transformer-json and the path to ${dir}/src/data. Unfortunately, graphQl isn't updating and doesn't see the json files in their project directories.

Expected result

I can query allProjectsJson to access project1's project.json and project2's project.json.

Actual result

I can only query allProject1Json or allProject2Json.

Environment

  System:
    OS: Linux 4.4 Ubuntu 18.04.2 LTS (Bionic Beaver)
    CPU: (8) x64 Intel(R) Core(TM) i7-6700HQ CPU @ 2.60GHz
    Shell: 4.4.19 - /bin/bash
  Binaries:
    Node: 10.16.3 - /usr/bin/node
    Yarn: 1.21.1 - /usr/bin/yarn
    npm: 6.9.0 - /usr/bin/npm
  Languages:
    Python: 2.7.15+ - /usr/bin/python
  Browsers:
    Chrome: 76.0.3809.132
    Firefox: 68.0.2
  npmPackages:
    gatsby: ^2.18.21 => 2.18.21
    gatsby-image: ^2.2.38 => 2.2.38
    gatsby-plugin-netlify-cms: ^4.1.37 => 4.1.37
    gatsby-plugin-netlify-cms-paths: ^1.3.0 => 1.3.0
    gatsby-plugin-postcss: ^2.1.19 => 2.1.19
    gatsby-plugin-sharp: ^2.3.13 => 2.3.13
    gatsby-source-filesystem: ^2.1.46 => 2.1.46
    gatsby-transformer-json: ^2.2.25 => 2.2.25
    gatsby-transformer-sharp: ^2.3.12 => 2.3.12
  npmGlobalPackages:
    gatsby-cli: 2.8.27
needs reproduction

Most helpful comment

Ahh, I see what you mean :)
luckily gatsby-transformer-json has a plugin option that will help get you unstuck!

It's the typeName option. You should be able to check for a field on each JSON node, and use that as the type name. Something like this:

    {
      resolve: `gatsby-transformer-json`,
      options: {
        typeName: ({ node, object, isArray }) =>
          object.project ? `Project` : `Json`,
      },
    },

That way anything with the field project defined will show up as allProject { ... }, where any other json files will show up as allJson { ... }

{
  allProject {
    nodes {
      project
    }
  }
}
{
  "data": {
    "allProject": {
      "nodes": [
        {
          "project": "project1"
        },
        {
          "project": "project2"
        }
      ]
    }
  }
}

All 8 comments

Hi @caseykey !

Thanks for providing a simple reproduction. Unfortunately it seems to be broken. gatsby-transformer-json is being used, but isn't installed. Once I installed it it errored on a missing image. If you can fix the reproduction, we'll be able to take a look :)

Thanks!

Hi @caseykey !

Thanks for providing a simple reproduction. Unfortunately it seems to be broken. gatsby-transformer-json is being used, but isn't installed. Once I installed it it errored on a missing image. If you can fix the reproduction, we'll be able to take a look :)

Thanks!

Fixed it, thanks for the help regarding the dependency.
In the 2nd browser tab, the one for GraphQl, you can see that there are queries available for allProject1Json and allProject2Json. I would like to access both of these transformed JSON via allProjectsJson as they are both under the projects folder in data. This would allow me to access images relative to each project's directory. The current behavior of accessing via allFolderNameJson doesn't work for me as content is added dynamically via NetlifyCMS and I won't know the folder names to make a query.

Ahh, I see what you mean :)
luckily gatsby-transformer-json has a plugin option that will help get you unstuck!

It's the typeName option. You should be able to check for a field on each JSON node, and use that as the type name. Something like this:

    {
      resolve: `gatsby-transformer-json`,
      options: {
        typeName: ({ node, object, isArray }) =>
          object.project ? `Project` : `Json`,
      },
    },

That way anything with the field project defined will show up as allProject { ... }, where any other json files will show up as allJson { ... }

{
  allProject {
    nodes {
      project
    }
  }
}
{
  "data": {
    "allProject": {
      "nodes": [
        {
          "project": "project1"
        },
        {
          "project": "project2"
        }
      ]
    }
  }
}

Ahh, I see what you mean :)
luckily gatsby-transformer-json has a plugin option that will help get you unstuck!

It's the typeName option. You should be able to check for a field on each JSON node, and use that as the type name. Something like this:

    {
      resolve: `gatsby-transformer-json`,
      options: {
        typeName: ({ node, object, isArray }) =>
          object.project ? `Project` : `Json`,
      },
    },

That way anything with the field project defined will show up as allProject { ... }, where any other json files will show up as allJson { ... }

{
  allProject {
    nodes {
      project
    }
  }
}
{
  "data": {
    "allProject": {
      "nodes": [
        {
          "project": "project1"
        },
        {
          "project": "project2"
        }
      ]
    }
  }
}

Hi Tyler!

Thanks for your help, it worked! Just had to make sure I was using backticks instead of single quotes for the ternary statement. If you want some StackOverflow cred I also posted this question here.

Glad to hear that helped! Thanks for the link. Just posted my first-ever SO answer ;)

@TylerBarnes
I added some new JSON files for the other sections of my website, so now the 'else' clause of the ternary statement you had in your solution is executing and causing an error.

`UNHANDLED REJECTION Cannot find ObjectTypeComposer with name Json

  Error: Cannot find ObjectTypeComposer with name Json`

Any clue why this is? Without the typename option for transfomer-json, Json appears to be a type.

It works if I add a new field to the new Json's and return that field as the else clause of the ternary statement. Example: object.project ? `Project` : object.section

@caseykey I'm not too sure actually. @vladar any idea?

I'm experiencing the same issue as @caseykey
As a workaround I used JsonFiles instead of Json

So in my case it's:

{
  resolve: `gatsby-transformer-json`,
  options: {
    typeName: ({ object }) => object.typeName || "JsonFiles"
  }
}
Was this page helpful?
0 / 5 - 0 ratings

Related issues

ghost picture ghost  路  3Comments

mikestopcontinues picture mikestopcontinues  路  3Comments

totsteps picture totsteps  路  3Comments

kalinchernev picture kalinchernev  路  3Comments

ferMartz picture ferMartz  路  3Comments