Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GraphQL - Get all fields from nested JSON object

Tags:

graphql

I'm putting a GraphQL wrapper over an exiting REST API as described in Zero to GraphQL in 30 minutes. I've got an API endpoint for a product with one property that points to a nested object:

// API Response
{
  entity_id: 1,
  nested_object: {
    key1: val1,
    key2: val2,
    ...
  }
}

Is it possible to define the schema so that I can get this entire nested object without explicitly defining the nested object and all of its properties? I want my query to just specify that I want the nested object, and not need to specify all the properties I want from the nested object:

// What I want
{
  product(id: "1") {
    entityId
    nestedObject
  }
}

// What I don't want
{
  product(id: "1") {
    entityId
    nestedObject {
      key1
      key2
      ...
    }
  }
}

I can do the second version, but it requires lots of extra code, including creating a NestedObjectType and specifying all the nested properties. I've also figured out how to automatically get a list of all the keys, like so:

const ProductType = new GraphQLObjectType({
  ...

  fields: () => ({
    nestedObject: {
      type: new GraphQLList(GraphQLString),
      resolve: product => Object.keys(product.nested_object)
    }
  })
})

I haven't figured out a way to automatically return the entire object, though.

like image 443
collinksmith Avatar asked May 05 '16 20:05

collinksmith


People also ask

How do you access nested elements in a JSON object?

We can parse a nested JSON object using the getString(index) method of JSONArray. This is a convenience method for the getJSONString(index). getString() method and it returns a string value at the specified position.

What is __ Typename in GraphQL?

The __typename field returns the object type's name as a String (e.g., Book or Author ). GraphQL clients use an object's __typename for many purposes, such as to determine which type was returned by a field that can return multiple types (i.e., a union or interface).

How do you create a nested query in GraphQL?

When setting up a field whose value is a custom type, we have to define a function that tells GraphQL how to get that custom type. In our case, we want to tell GraphQL how to get the posts if we have the author. We do that by defining a new root property inside resolvers.

Does GraphQL return JSON?

After being validated, a GraphQL query is executed by a GraphQL server which returns a result that mirrors the shape of the requested query, typically as JSON.


2 Answers

You may try to use scalar JSON type. You can find more here (based on apollographql).

  • add scalar JSON to a schema definition;
  • add {JSON: GraphQLJSON} to a resolve functions;
  • use JSON type in a shema:

    scalar JSON
    type Query {
        getObject: JSON
    }

  • an example of a query:

    query {
      getObject
    }

  • a result:

    {
      "data": {
        "getObject": {
          "key1": "value1",
          "key2": "value2",
          "key3": "value3"
        }
      }
    }

Basic code:


    const express = require("express");
    const graphqlHTTP = require("express-graphql");
    const { buildSchema } = require("graphql");
    const GraphQLJSON = require("graphql-type-json");

    const schema = buildSchema(`
      scalar JSON

      type Query {
        getObject: JSON
      }
    `);

    const root = {
      JSON: GraphQLJSON,

      getObject: () => {
        return {
          key1: "value1",
          key2: "value2",
          key3: "value3"
        };
      }
    };

    const app = express();
    app.use(
      "/graphql",
      graphqlHTTP({
        schema: schema,
        rootValue: root,
        graphiql: true
      })
    );
    app.listen(4000);
    console.log("Running a GraphQL API server at localhost:4000/graphql");

like image 149
Alexander Fedorov Avatar answered Oct 06 '22 03:10

Alexander Fedorov


I can do the second version, but it requires lots of extra code, including creating a NestedObjectType and specifying all the nested properties.

Do it! It will be great. That's the way to go in order to use GraphQL to its full potential.

Aside from preventing over-fetching, it also gives you a lot of other benefits like type validation, and more readable and maintainable code since your schema gives a fuller description of your data. You'll thank yourself later for doing the extra work up front.

If for some reason you really don't want to go that route though and fully understand the consequences, you could encode the nested objects as strings using JSON.stringify.

But like I said, I recommend you don't!

like image 25
Eric Streeper Avatar answered Oct 06 '22 04:10

Eric Streeper