[Java] Sample code to call Yahoo! Shopping Product Search (v3) API with HTTP Client API officially introduced from Java 11

5 minute read

Overview

–Create a sample program that calls the Yahoo! Shopping Product Search (v3) API using the HTTP Client API officially introduced from Java 11 (HttpClient, HttpRequest, HttpResponse classes, etc. of the java.net.http package).

This environment

  • Java 11 (AdoptOpenJDK 11.0.7+10)
  • Jackson Databind 2.11.0
  • Gradle 6.5
  • macOS Catalina

Source code

Source code list

├── build.gradle
└── src
    └── main
        └── java
            └── com
                └── example
                    ├── ErrorResponse.java
                    ├── ItemSearch.java
                    └── ResultSet.java

build.gradle

plugins {
  id 'application'
  id 'java'
}

group 'org.example'
version '0.0.1'
mainClassName = "com.example.ItemSearch"
sourceCompatibility = '11'

repositories {
  mavenCentral()
}

dependencies {

  //Required for JSON and class mapping
  // https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind
  implementation 'com.fasterxml.jackson.core:jackson-databind:2.11.0'
}

src/main/java/com/example/ItemSearch.java

package com.example;

import com.fasterxml.jackson.databind.ObjectMapper;

import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.time.Duration;

/**
 *shopping:Product search (v3)- Yahoo!Developer network
 * https://developer.yahoo.co.jp/webapi/shopping/shopping/v3/itemsearch.html
 */
public class ItemSearch {

  public static void main(String[] args) {

    try {
      String appid = args[0];
      String query = args[1];
      System.out.println("appid: " + appid); //Application ID
      System.out.println("query: " + query); //Search keyword

      //Search for products
      ResultSet rs = new ItemSearch().search(appid, query);
      if (rs != null) {
        for (ResultSet.Hit hit : rs.hits) {
          System.out.println("**************************************************");
          System.out.println("Product name: " + hit.name);
          System.out.println("Description of item: " + hit.description);
          System.out.println("catch copy: " + hit.headLine);
          System.out.println("76 x 76 size image URL: " + hit.image.small);
          System.out.println("Image URL of 146 x 146 size: " + hit.image.medium);
          System.out.println("Product URL: " + hit.url);
          System.out.println("price: " + hit.price);
        }
      }
    } catch (Exception e) {
      System.out.println("Error occurred: " + e);
      e.printStackTrace();
    }
  }

  /**
   *Search for products.
   * @param appid application ID
   * @param query Search keyword
   * @return search results
   * @throws Exception when an error occurs
   */
  public ResultSet search(String appid, String query) throws Exception {

    try {
      //Build URLs for API calls
      String baseurl = "https://shopping.yahooapis.jp/ShoppingWebService/V3/itemSearch";
      String url = baseurl +
        "?query=" + URLEncoder.encode(query, StandardCharsets.UTF_8) + //Search keyword
        "&results=2"; //Up to 2 search results
      System.out.println("URL: " + url);

      //Build HTTP request information
      HttpRequest req = HttpRequest.newBuilder(new URI(url))
        .GET()
        .setHeader("User-Agent", "Yahoo AppID: " + appid) //Application ID
        .timeout(Duration.ofSeconds(10))
        .build();

      //Call the API to get the result
      HttpClient client = HttpClient.newBuilder()
        .version(HttpClient.Version.HTTP_1_1)
        .followRedirects(HttpClient.Redirect.NORMAL)
        .connectTimeout(Duration.ofSeconds(10))
        .build();
      HttpResponse<String> res = client.send(req, HttpResponse.BodyHandlers.ofString());
      String body = res.body();

      //Output the status code of the response
      int statusCode = res.statusCode();
      System.out.println("statusCode: " + statusCode);

      //Judge success / failure by status code
      switch (res.statusCode()) {
        case 200:
          //Map the JSON of the HTTP response to the ResultSet class
          return new ObjectMapper().readValue(body, ResultSet.class);
        case 403:
          //Output error information
          ErrorResponse errorResponse = new ObjectMapper().readValue(body, ErrorResponse.class);
          System.out.println("Error message: " + errorResponse.error.message);
          return null;
        default:
          return null;
      }

    } catch (Exception e) {
      throw e;
    }
  }
}

src/main/java/com/example/ResultSet.java

A class that represents the response of search results.

package com.example;

import com.fasterxml.jackson.annotation.JsonIgnoreProperties;

import java.util.List;

/**
 *search results.
 */
@JsonIgnoreProperties(ignoreUnknown = true) //Ignore unknown JSON properties
public class ResultSet {

  public List<Hit> hits;

  @JsonIgnoreProperties(ignoreUnknown = true) //Ignore unknown JSON properties
  public static class Hit {

    // hits/name string Product name
    public String name;

    // hits/description string Item description
    public String description;

    // hits/headLine string catch phrase
    public String headLine;

    // hits/image
    public Image image;

    // hits/url string product url
    public String url;

    // hits/price integer price
    public int price;
  }

  public static class Image {

    // hits/image/small string 76 x 76 size image URL
    public String small;

    // hits/image/medium string 146 x 146 size image URL
    public String medium;
  }
}

src/main/java/com/example/ErrorResponse.java

A class that represents error response information.

import com.fasterxml.jackson.annotation.JsonProperty;

/**
 *Error information.
 */
public class ErrorResponse {

  @JsonProperty("Error")
  public Error error;

  public static class Error {

    @JsonProperty("Message")
    public String message;
  }
}

Execution example

Specify the available application ID and search keyword “cat”

The response of the search result is mapped to the ResultSet class and the information is output.

$ gradle run -q --args="your_application_id cat"
appid: your_application_id
query:Cat
URL: https://shopping.yahooapis.jp/ShoppingWebService/V3/itemSearch?query=%E7%8C%AB&results=2
statusCode: 200
**************************************************
Product name:Cat harness, cat leash, cat supplies, pet supplies
Description of item:As an escape measure<br><br>Cats often panic and try to escape or rampage when they are moved unfamiliarly, such as when they go to the hospital or move. In such a case, it is very safe not only to put it in the pet cage, but also to put it in the pet cage after attaching the harness. Also, in the unlikely event that you have to evacuate due to a major disaster, it will help prevent escape, so more and more owners are keeping it in their disaster prevention goods.<br><br>For a walk<br><br>脱走防止目的だけでなく、猫のFor a walk使用するのもおすすめです。ハーネスは猫の身体の動きを邪魔しにくいので、のびのびと運動できて良いストレス発散になることでしょう。ただし、猫の性格によっては外に連れ出すことがかえってストレスとなる場合もありますので、お散歩はくれぐれも猫の様子をみつつ、交通状況などにも気を配りながら行ってください。<br><br>There are four color variations: red, blue, black, and pink.<br>Made of nylon<br><br>Neck circumference 16-26 cm<br>Girth 26-36 cm<br>Lead length 110 cm<br><br>Search keywords: cat leash, cat harness, cat leash, point digestion, free shipping
catch copy:Cat harness cat leash cat leash cat collar
76 x 76 size image URL: https://item-shopping.c.yimg.jp/i/c/sam-store_0030
Image URL of 146 x 146 size: https://item-shopping.c.yimg.jp/i/g/sam-store_0030
Product URL: https://store.shopping.yahoo.co.jp/sam-store/0030.html
price: 599
**************************************************
Product name:Cat toys fish robot cat electric toys cat automatic toys cat toys automatic cat toys electric cat toys fish
Description of item:[Pet toys] Electric fish robot Fish robot Toy cat Electric toy cat<br>[Automatic swimming function] Automatically turned on by the water sensor/Turn off. Designed with automatic robot fins<br>It starts moving as soon as it is placed in water, and automatically turns off when taken out, saving power.<br>[With LED light] Since the LED light is built-in, it glows in the dark. The shining and moving fish tickle the animal's hunting instinct<br>[Product usage scene] Automatic cat toys<br>[Applicable pets] Scottish Fold Maine Coon Ragdoll Russian Blue British Show Hair<br>Siberian Kijitora Stray Cat American Curl Scottish Sabatra Hachiware Neko-chan<br>
catch copy:An electric fish robot that stimulates the hunting instinct of cats
76 x 76 size image URL: https://item-shopping.c.yimg.jp/i/c/himawaridifang-store_robo-fish1
Image URL of 146 x 146 size: https://item-shopping.c.yimg.jp/i/g/himawaridifang-store_robo-fish1
Product URL: https://store.shopping.yahoo.co.jp/himawaridifang-store/robo-fish1.html
price: 880

Specify an unusable application ID and search keyword “cat”

The error response is mapped to the ErrorResponse class and the information is output.

$ gradle run -q --args="invalid_application_id cat"
appid: invalid_application_id
query:Cat
URL: https://shopping.yahooapis.jp/ShoppingWebService/V3/itemSearch?query=%E7%8C%AB&results=2
statusCode: 403
Error message: Your Request was Forbidden

Reference material

-Shopping: Product Search (v3) -Yahoo ! Developer Network