Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[source-contentful] [Discussion] JSON entry type as plain old JS Object #1703

Closed
m4rrc0 opened this issue Aug 3, 2017 · 13 comments · May be fixed by ajesse11x/gatsby#719, philipedin/gatsby#835 or harunpehlivan/gatsby#782

Comments

@m4rrc0
Copy link
Contributor

m4rrc0 commented Aug 3, 2017

For now, JSON entry types in contentful are managed like local JSON. You have to know the structure of your JSON to query every bit of it that you need. IMO JSON entry types in Contentful serves another purpose. If I know exactly what fields I need I would just create text fields. I would like to use JSON fields as returning a plain old JS object without the need to query inside it.
A pretty straightforward example: Imagine I have a content type for pages. I could add a JSON field for css styles specific to that page. Obviously the properties in my JSON entry will be different for every page.

Anyone a thought about this? A counter-argument maybe?

@sebastienfi
Copy link
Contributor

I was faced with the same use case when doing gatsby-source-wordpress.

In my scenario that wouldn't be the styles but the page contents itself that would be dynamic, changing from page to page, so making it impossible to query it using GraphQL. I ended up with creating a new GraphQL node of type application/json child-linked to the source node and which contains the stringyfied version of the JSON. Then I query it in GraphQL, and call JSON.Parse() to retrieve the "unique" datamodel.

I suppose that keeping that entry of type JSON as a string is a good idea. Maybe someone have another use case ?

@m4rrc0
Copy link
Contributor Author

m4rrc0 commented Sep 6, 2017

Thanks @sebastienfi . glad to know I am not the only one facing this kind of issue.
@Khaledgarbaya can you think of a use case where it would NOT be a good idea to stringify JSON entry types?
I can imagine a content type with a complex structure. It may be easier to copy/paste a json as is than create a bunch of text fields. But since it is a matter of compromise anyway, user could as well fetch the whole json object in that case...

We can also try and make both usages coexist. Maybe put a flag somewhere or decide a specific property name to be used if user wants its content to be stringified...?

@Khaledgarbaya
Copy link
Contributor

Hey @MarcCoet most of the time a JSON field is used as a configuration for another library etc. I don't see people interacting with the JSON data directly, they will be pulling it and pass it along to another lib/framework etc.

@m4rrc0
Copy link
Contributor Author

m4rrc0 commented Sep 7, 2017

Ok, so you agree it makes sense to pull json fields as string in gatsby?

@Khaledgarbaya
Copy link
Contributor

Yeah It makes sense to get it as a String

@sarahatwork
Copy link
Contributor

@Khaledgarbaya @MarcCoet @sebastienfi I ran into this issue as well and created a PR #2967 with a "make both usages coexist" solution (although I agree needing a stringified version is the more common use case). If you have time to look it over, I'd be interested in hearing your thoughts.

@KyleAMathews
Copy link
Contributor

@sarahatwork curious why you'd do translations as a JSON string instead of using Contentful's localization features? Seems like that'd just complicate your life? I'm sure there's reasons but generally Gatsby (and Contentful) push people towards structured data as that simplifies a lot of things.

@sarahatwork
Copy link
Contributor

@KyleAMathews This seemed like a good solution for "utility strings" that don't correspond to module instances, like the words "Close" and "Menu." They're things I'd normally save locally as some kind of language bundle, but since I'm using Contentful anyway, I figured it'd be best to put all my strings in one place, so updating translations won't require a new code deploy.

I'm using Contentful's localization features for everything else- for example I have a BodyText content type, and the main content field is localized so editors can include localized copy.

@Khaledgarbaya
Copy link
Contributor

Hi @sarahatwork, your solution looks great my only concern is having this internal.content just for the JSON Node which can create some inconsistency

@sarahatwork
Copy link
Contributor

@Khaledgarbaya It's already a property created for text nodes: https://github.com/gatsbyjs/gatsby/pull/2967/files#diff-0f3299a5d7eb6ef91bdf3a22e5059e0fR153

But I'm definitely open for moving/renaming it!

It might be helpful to look at the two functions together:

// existing function

function createTextNode(node, key, text, createNode) {
  const str = _.isString(text) ? text : ` `
  const textNode = {
    id: `${node.id}${key}TextNode`,
    parent: node.id,
    children: [],
    [key]: str,
    internal: {
      type: _.camelCase(`${node.internal.type} ${key} TextNode`),
      mediaType: `text/markdown`,
      content: str,
      contentDigest: digest(str),
    },
  }

  node.children = node.children.concat([textNode.id])
  createNode(textNode)

  return textNode.id
}

// added by me

function createJSONNode(node, key, content, createNode) {
  const str = JSON.stringify(content)
  const JSONNode = {

    // I decided to spread `content` rather than using `[key]: content,` like above,
    // since that felt like that added an extra query layer, but it's something we could do.
    // It would prevent name collisions.

    ...content, 
    id: `${node.id}${key}JSONNode`,
    parent: node.id,
    children: [],
    internal: {
      type: _.camelCase(`${node.internal.type} ${key} JSONNode`),
      mediaType: `application/json`,
      content: str,
      contentDigest: digest(str),
    },
  }

  node.children = node.children.concat([JSONNode.id])
  createNode(JSONNode)

  return JSONNode.id
}

@Khaledgarbaya
Copy link
Contributor

@sarahatwork ah yeah, sorry I missed that

@m4rrc0
Copy link
Contributor Author

m4rrc0 commented Nov 22, 2017

So that's how you get a PR approved... Thanks for the lesson @sarahatwork . ;)
Nice touch using intenal.content. Thanks for moving this forward. I'll close this issue as soon as the PR gets merged.

@KyleAMathews
Copy link
Contributor

thanks everyone!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
5 participants