3

I am new to GraphQL and not really sure if this problem is my lack of JavaScript knowledge or GraphQL.

My GraphQL queries an external service and when the response is a scalar json object everything works great. The problem comes when the external service returns an array of json.

This works for a single json result:

const transform = (json) => {
  return {
    id: json.id,
    fullname: json.fullName,
    email: json.email
}

But for an array like this the mapping code is inadequate.

[{id:...fullname:...email:...},{id:...etc},{id:...etc}]

Now I can detect that the return is an array and I can loop through the array just not sure how to map into a GraphQLList.

So after Googling I found GraphQLList but it doesn't work either.

...snip from Schema...
UserData: {
        type: GraphQLLIst(UserType),

same mapping code as above.

message": "Expected Iterable, but did not find one for field RootQueryType.investorData.

But I'm confused because the console log clearly shows a json array?


GraphQLSchema

const RootQueryType = new GraphQLObjectType({
   name: 'RootQueryType',
   fields:{
    investorData: {
        type: new GraphQLList(UserType),
        description: 'Get investors by id',
        args:{key: {type: GraphQLString} },
        resolve: resolveInvestorData
       }
     }
   }
})
2
  • Could you post your GraphQL schema? What is the type you defined for investorData field? Commented Jan 27, 2019 at 12:23
  • @YevheniiHerasymchuk. Schema posted. Commented Jan 27, 2019 at 22:57

1 Answer 1

1

Problem is solved but not by any genius on my part but rather dumb luck.

So by adding mapping code I am actually interfering with GraphQL's mapping.

This is wrong but posted here for before and after comparison.

GraphQLSchema:

const RootQueryType = new GraphQLObjectType({ name: 'RootQueryType',

fields: {    
    userData: {
        type: new GraphQLList(UserType),
        args:{key: {type: GraphQLString} },
        resolve: resolveUserData
       }
    }
  }
})

ResolveUserData:

return fetch(url)
   .then(response => {
      return response.json()
      })
   .then(json => {
      return transformUser(json)
      })
   .catch(err => {
      console.trace(err)
     })  
  }

const transformUser = (json) => {
  console.trace(json);
  return {
    id: json.id,
    portfolioid: json.portfolioID,
    fullname: json.fullName,
    email: json.email
   }
}

Correct returned data mapping. (Hint NO MAPPING)

return fetch(url)
   .then(response => {
      return response.json()
      })
   .catch(err => {
      console.trace(err)
     })  
  }

Now this is MY final solution as I wanted one endpoint to handle both a single lookup and a "Get All" request. Feel free to comment on this architecture.

const resolveUserData = (obj, args) => {

let url = '';

//if branch to determine if one user or all
if (typeof args.key === "undefined") {
    url = 'http://localhost:5001/api/users';
}
else
{
    url = 'http://localhost:5001/api/users/' + args.key;
}

return fetch(url)
.then(response => {
  return response.json()
})
.then(json => {
    if(!Array.isArray(json))
    {
        var jarray = [];
        jarray.push(json);
        return jarray;
    }
    return json
})
.catch(err => {
  console.trace(err)
})  

}

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.