2
votes

I am experimenting with GraphQL on Android using apollo-client and am using GitHub's GraphQL API. I am hitting an API to give me a list of repos owned by a user. Everything works fine but the response that I get is not in JSON format but in String format.

The response looks like this:

Data{user=User{__typename=User, 
repositories=Repositories{__typename=RepositoryConnection, nodes= 
[Node{__typename=Repository, name=testrepository}]}}

when I try hitting the url through Insomnia (GraphQL rest client) I get the response in JSON format but in my app I get the response in above format. I tried passing content-type : "application/json; charset=utf-8" in header but no success.

Here is how I am fetching the response:

public void fetchRepoList(String userName, String authHeader, final ResponseCallback responseCallback) {
    GraphQL.getInstance().getApolloClient(authHeader)
            .query(githubRepoList.repoListAPI.FindQuery.builder().repoOwner(userName).build())
            .enqueue(new ApolloCall.Callback<githubRepoList.repoListAPI.FindQuery.Data>() {
                @Override
                public void onResponse(@Nonnull Response<githubRepoList.repoListAPI.FindQuery.Data> response) {
                  Log.d(TAG, "response" + response)
                }

                @Override
                public void onFailure(@Nonnull final ApolloException exception) {

                }
            });
}

I want to put the response in a List of Model class and for that I need the response in JSON format. Searched for this issue but didn't got any proper solution.

I am using apollo client 0.3.2

[Edit:1]

I tried making the call to the GitHub GraphQL API with Okhttp and this time I got this response:

{"data":{"__schema":{"queryType":{"name":"Query"},"mutationType":{"name":"Mutation"},"subscriptionType":null,"types":[{"kind":"SCALAR","name":"Boolean","description":"Represents `true` or `false` values.","fields":null,"inputFields":null,"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"SCALAR","name":"String","description":"Represents textual data as UTF-8 character sequences. This type is most often used by GraphQL to represent free-form human-readable text.","fields":null,"inputFields":null,"interfaces":null,"enumValues":null,"possibleTypes":null},{"kind":"OBJECT","name":"Query","description":"The query root of GitHub's GraphQL interface.","fields":[{"name":"codeOfConduct","description":"Look up a code of conduct by its key","args":[{"name":"key","description":"The code of conduct's key","type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"String","ofType":null}},"defaultValue":null}],"type":{"kind":"OBJECT","name":"CodeOfConduct","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"codesOfConduct","description":"Look up a code of conduct by its key","args":[],"type":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"CodeOfConduct","ofType":null}},"isDeprecated":false,"deprecationReason":null},{"name":"license","description":"Look up an open source license by its key","args":[{"name":"key","description":"The license's downcased SPDX ID","type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"String","ofType":null}},"defaultValue":null}],"type":{"kind":"OBJECT","name":"License","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"licenses","description":"Return a list of known open source licenses","args":[],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"LIST","name":null,"ofType":{"kind":"OBJECT","name":"License","ofType":null}}},"isDeprecated":false,"deprecationReason":null},{"name":"marketplaceCategories","description":"Get alphabetically sorted list of Marketplace categories","args":[{"name":"includeCategories","description":"Return only the specified categories.","type":{"kind":"LIST","name":null,"ofType":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"String","ofType":null}}},"defaultValue":null},{"name":"excludeEmpty","description":"Exclude categories with no listings.","type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null},{"name":"excludeSubcategories","description":"Returns top level categories only, excluding any subcategories.","type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null}],"type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"LIST","name":null,"ofType":{"kind":"NON_NULL","name":null,"ofType":{"kind":"OBJECT","name":"MarketplaceCategory","ofType":null}}}},"isDeprecated":false,"deprecationReason":null},{"name":"marketplaceCategory","description":"Look up a Marketplace category by its slug.","args":[{"name":"slug","description":"The URL slug of the category.","type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"String","ofType":null}},"defaultValue":null},{"name":"useTopicAliases","description":"Also check topic aliases for the category slug","type":{"kind":"SCALAR","name":"Boolean","ofType":null},"defaultValue":null}],"type":{"kind":"OBJECT","name":"MarketplaceCategory","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"marketplaceListing","description":"Look up a single Marketplace listing","args":[{"name":"slug","description":"Select the listing that matches this slug. It's the short name of the listing used in its URL.","type":{"kind":"NON_NULL","name":null,"ofType":{"kind":"SCALAR","name":"String","ofType":null}},"defaultValue":null}],"type":{"kind":"OBJECT","name":"MarketplaceListing","ofType":null},"isDeprecated":false,"deprecationReason":null},{"name":"marketplaceListings","description":"Look up Marketplace listings","args":[{"name":"after","description":"Returns the elements in the list that come after the specified cursor.","type"

This response doesn't even have required data about the repositories. It is not even related to the list of repositories.

Therefore, I went back to the old method and made the call using apollo. Now, since apollo creates these model classes from standard GraphQL queries, how do I create a list of this model class.

I went through the apollo sample-app on github and came across this piece of code:

List<FeedEntry> feedResponseToEntriesWithRepositories(Response<FeedQuery.Data> response) {
List<FeedEntry> feedEntriesWithRepos = new ArrayList<>();
final FeedQuery.Data responseData = response.data();
if (responseData == null) {
  return Collections.emptyList();
}
final List<FeedEntry> feedEntries = responseData.feedEntries();
if (feedEntries == null) {
  return Collections.emptyList();
}
for (FeedEntry entry : feedEntries) {
  if (entry.repository() != null) {
    feedEntriesWithRepos.add(entry);
  }
}
return feedEntriesWithRepos;
}

Here the feedEntries() method returns the list of feeds, this method is in the auto-generated model class file in the apollo directory. I went and checked my model file and there were no methods which returns a list of repos (as in my case). The file is too large to post here but if community want's to have a look at it I can post it here.

By the way, I tried something like this with my code:

List<githubRepoList.repoListAPI.FindQuery.Node> repoList = new ArrayList<>();
final githubRepoList.repoListAPI.FindQuery.Data repoListData = response.data();
final List<githubRepoList.repoListAPI.FindQuery.Node> finalRepoList = repoListData.(which method to call from the auto-generated class file?)

Here, Node is a class in my auto-generated model file in the apollo directory and this class should have a method which returns a list of repo model class.

I know I am doing something wrong here. I think there is some other way to create of list of these model classes.

1
"The response looks like this" -- please provide a minimal reproducible example showing how you are getting that output. This looks like it is a toString() implementation of a Data class, which might be perfectly reasonable.CommonsWare
@CommonsWare I have edited my questionlocalhost
@CommonsWare Yes, I am using toString() but the response is not in JSON formatlocalhost

1 Answers

1
votes

the response is not in JSON format

The response was in JSON format. It is now in the form of a githubRepoList.repoListAPI.FindQuery.Data object. That class was code-generated for you based on your GraphQL document. Quoting the Apollo-Android documentation, with emphasis added:

Apollo-Android is a GraphQL compliant client that generates Java models from standard GraphQL queries

In particular, Apollo-Android generates toString() implementations on those Java model classes. In your case:

  • Data holds a User in a user field
  • User holds a RepositoriesConnection, renamed to Repositories, in a repositories field
  • The repositories collection holds a single Repository

The reason for using Apollo-Android is so that you do not have to deal with the JSON yourself. If, instead, you want to parse JSON yourself, get rid of Apollo-Android and just use OkHttp to make the Web service calls.