1

I can’t seem to work out the nested objects from a Json response. Here is my code:

    import com.fasterxml.jackson.annotation.JsonCreator;
    import com.fasterxml.jackson.annotation.JsonProperty;
    import com.fasterxml.jackson.core.type.TypeReference;
    import com.fasterxml.jackson.databind.JsonNode;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.google.gson.Gson;
    import com.google.gson.reflect.TypeToken;
    import com.sun.xml.internal.org.jvnet.fastinfoset.stax.LowLevelFastInfosetStreamWriter;
    import io.sphere.sdk.categories.Category;
    import io.sphere.sdk.client.HttpRequestIntent;
    import io.sphere.sdk.client.JsonNodeSphereRequest;
    import io.sphere.sdk.client.SphereRequest;
    import io.sphere.sdk.http.HttpMethod;
    import io.sphere.sdk.http.HttpResponse;
    import io.sphere.sdk.json.SphereJsonUtils;
    import io.sphere.sdk.models.Base;
    import io.sphere.sdk.models.LocalizedString;
    import com.google.gson.Gson;

    import javax.annotation.Nullable;
    import java.lang.reflect.Type;
    import java.time.LocalDateTime;
    import java.util.*;


    public class EvaProduct {

        private String id;
        private LocalDateTime createdAt;
        private LocalDateTime lastModifiedAt;
        private LocalizedString name;
    //    private LocalizedString description;
    //    private Set<Category> categories;
    //    private Set<EvaVariant> veloVariants = new HashSet<>();


        @JsonCreator
        EvaProduct(@JsonProperty("id")  String id,
                   @JsonProperty("crdAt") LocalDateTime createdAt,
                   @JsonProperty("lastModifiedAt") LocalDateTime lastModifiedAt,
                   @JsonProperty("name") LocalizedString name ){

            this.id = id;
            this.createdAt = createdAt;
            this.lastModifiedAt = lastModifiedAt;
            this.name = name;
        }

        public String getId() {
            return id;
        }

        public LocalDateTime getCreatedAt() { return createdAt; }

        public LocalDateTime getLastModifiedAt() {
            return lastModifiedAt;
        }

        public LocalizedString getName(){
            return name;
        }


        static SphereRequest<List<EvaProduct>> getAllEvaProducts(){
            return new GetAllEvaProducts();
        }


        @Override
        public String toString() {
            return "EvaProduct {" +
                    "id='" + id + '\'' +
                    ", createdAt=" + createdAt +
                    ", lastModifiedAt=" + lastModifiedAt +
                    ", name=" + name +
                    '}';
        }

        private static class GetAllEvaProducts extends Base implements SphereRequest<List<EvaProduct>> {

            public static final int MAX = 2;


            @Nullable
            @Override
            public List<EvaProduct> deserialize(HttpResponse httpResponse) {

                final JsonNode rootJsonNode = SphereJsonUtils.parse(httpResponse.getResponseBody());

                final JsonNode results = rootJsonNode.get("data").get("products").get("results");

                List<EvaProduct> evaProducts = SphereJsonUtils.readObject(results, new TypeReference<List<EvaProduct>>() { });

                return evaProducts;
            }

            @Override
            public HttpRequestIntent httpRequestIntent() {
                final String queryString = String.format("query product {\n" +
                        "       products(limit: %d) {\n" +
                        "           results {\n" +
                        "               id\n" +
                        "               createdAt\n" +
                        "               lastModifiedAt\n" +
                        "               masterData{\n" +
                        "                   current{\n" +
                        "                   name(locale: \"en\")" +
                        "                   }\n" +
                        "               }\n" +
                        "           }\n" +
                        "       }\n" +
                        "   }", MAX);
                final String body =String.format(
                        "{\n" +
                                "   \"query\": \"%s\"" +
                                "}", queryString.replace("\n", "\\n").replace("\"", "\\\""));
                return HttpRequestIntent.of(HttpMethod.POST, "/graphql", body);
            }
        }

    }

And from the Controller:

    import io.sphere.sdk.client.SphereClient;
    import io.sphere.sdk.client.SphereRequest;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;

    import java.io.IOException;
    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.CompletionStage;
    import java.util.concurrent.ExecutionException;

    import static handson.impl.ClientService.createSphereClient;
    import static handson.EvaVariant.requestOfSkusEvaProducts;
    import static handson.EvaProduct.getAllEvaProducts;


    public class ZEvaKnowsGraphQL {
        private static final Logger LOG = LoggerFactory.getLogger(ZEvaKnowsGraphQL.class);

        public static void main(String[] args) throws IOException, ExecutionException, InterruptedException {
            try (final SphereClient client = createSphereClient()) {

                SphereRequest<List<EvaProduct>> allEvaProducts = getAllEvaProducts();

                CompletionStage<List<EvaProduct>> listCompletionStage = client.execute((allEvaProducts));

                List<EvaProduct> evaProducts1 = listCompletionStage.toCompletableFuture().get();

                for(EvaProduct evaProduct: evaProducts1) {
                    System.out.println(evaProduct.toString());
                }
            }
        }
    }

I managed to get a complete result from a GraphQL request, so the JsonNode results has all the right values. For example it looks like this:

[{"id":"098834e3-e636-4186-91e5-30176ee3c261","createdAt":"2019-12-18T14:38:53.617Z","lastModifiedAt":"2019-12-18T14:38:53.617Z","masterData":{"current":{"name":"cookie-BlueWine"}}},{"id":"238135fb-3fa0-4f54-9e52-d70e5bd38b43","createdAt":"2019-12-18T14:38:53.631Z","lastModifiedAt":"2019-12-21T19:22:33.324Z","masterData":{"current":{"name":"cookie-RedWinerru"}}}]

However I can’t seem to get the nested name value into my Java objects. So evaProducts now looks like this:

EvaProduct {id='098834e3-e636-4186-91e5-30176ee3c261', createdAt=2019-12-18T14:38:53.617, lastModifiedAt=2019-12-18T14:38:53.617, name=null} EvaProduct {id='238135fb-3fa0-4f54-9e52-d70e5bd38b43', createdAt=2019-12-18T14:38:53.631, lastModifiedAt=2019-12-21T19:22:33.324, name=null}

So name is null. Can somebody give me a hint as to how solve this issue? How do I get the nested value into the right field?

Gander
  • 1,854
  • 1
  • 23
  • 30
Eva
  • 11
  • 2

2 Answers2

0

In your graphQL query you query for English translation with name(locale: \"en\")" so the result will be directly the String for English and can't be parsed as LocalizedString which is a kind of a Map of Strings per locale.

To fix this you need to change in your EvaProduct class the name field to String or just update your query for to get the object for all locales.

Schleichardt
  • 7,502
  • 1
  • 27
  • 37
0

Oll'right, so I figured out the answer somewhere. Yes @Schleichardt, also the LocalizedString needs to be changed into a String, thank you for this, but also: I need to add a field: private final Map masterData; It will get the masterdata from the response and then I can use this in the jsonCreator/constructor to extract the values for the name like this: this.name = ((String)((Map)masterdata.get("current")).get("name")); Et voila, it works!

Eva
  • 11
  • 2