1

I have a rest API that returns an object with a list of ids with counts on each of them.

{
    "orders": {
      "PMY5XbR7FZo5qEkEb": 0
    }
}

I have no idea what the keys of the orders object will be ahead of time, nor do I know how many keys there will be.

This question's response suggests using a JSON type, which is risky but do-able.

The problem is that this doesn't work with a graphQL yoga server:

type Task {
  orders:  JSON
}

How do I refer to JSON types in a yoga server?

Josh Pittman
  • 7,024
  • 7
  • 38
  • 66
  • I don't recommend this approach any more than the answers to that question, but you need to declare `scalar JSON` to make it work. A better approach would be to map that object to a `type Order { id: ID!, count: Int! }`. – David Maze Jan 19 '19 at 11:24
  • Can you explain what you mean by "you need to declare scalar JSON", sorry, I don't understand what that means. – Josh Pittman Jan 19 '19 at 11:27
  • 1
    Put the words `scalar JSON` in your GraphQL schema somewhere at the top level. You need to [explicitly declare scalar types](https://graphql.org/learn/schema/#scalar-types) though GraphQL itself doesn't give any particular meaning to them. – David Maze Jan 19 '19 at 11:28
  • It worked. Amazing. thank you very much. If you repost that response as an answer, I can mark it answered. I know it may seem insignificant given how simple it was, but that was a huge help for me and will most likely be for someone else looking to return an object. Returning a dynamic object seems like such a common thing, surprised there isn't a better solution. – Josh Pittman Jan 19 '19 at 11:54

1 Answers1

1

You need to explicitly declare scalar types before you can use them. For this schema to work you need to add an additional declaration:

scalar JSON
type Task {
  orders:  JSON
}

GraphQL doesn't know anything about the contents of the scalar values, which means this is pushing additional processing work off to the client (to validate and deserialize the JSON) and this doesn't really describe your object model.

You might consider rearranging the backend response to have a more structured object model. As an API consumer I would find it easier to understand and use

type Order {
  id: ID!
  count: Int!
}
type Task {
  orders: [Order!]!
}

but you can't directly pass through the backend REST API result to this form without rearranging it.

David Maze
  • 130,717
  • 29
  • 175
  • 215
  • Thank you. The only problem with the second solition is that I don't have control over the rest endpoint. It gives me an object with dynamic keys and of an uncertain amount. Can I still apply your second solution if I can't change this response? – Josh Pittman Jan 19 '19 at 12:36
  • 1
    From your question it sounds like your resolver function for the `orders` field makes the REST call to the backend. Your proposed solution is to take that response and serialize it to a JSON string before returning it; at the same place, after the REST call returns but before you make the GraphQL response, you have a chance to rearrange the data. – David Maze Jan 19 '19 at 12:39
  • I understand what you mean now. Thanks David. – Josh Pittman Jan 20 '19 at 09:29