Home > Net >  Extract data from YouTube Data API with Java / Sprint Boot
Extract data from YouTube Data API with Java / Sprint Boot

Time:02-14

I am trying to extract title, videoId, and description data of all the videos I got from using YT Data API. I was able to return the data in what looks like JSON format (but it is actually LinkedHashMap when I check with getClass()) in Postman and Chrome browser, but was unable to extract the value from specific keys I have mentioned above.

I tried:

System.out.println((rest.getForObject(url, Object.class, params)).get("items")); It asks me to cast to JSONObject

Overall, I need to extract the data and convert into xml before sending it over to ActiveMQ

Edit: Format I get in Postman/Chrome browser

{
  "kind": "youtube#searchListResponse",
  "etag": "3LV4enCWAzOaiqJb_cMIUVklXJY",
  "nextPageToken": "CAUQAA",
  "regionCode": "CA",
  "pageInfo": {
    "totalResults": 478712,
    "resultsPerPage": 5
  },
  "items": [
    {
      "kind": "youtube#searchResult",
      "etag": "gt6x7J2XpzU8Mpb3yv9_HmNTzWY",
      "id": {
        "kind": "youtube#video",
        "videoId": "I_ZK0t9-llo"
      },
      "snippet": {
        "publishedAt": "2021-03-01T18:15:13Z",
        "channelId": "UC2WHjPDvbE6O328n17ZGcfg",
        "title": "Stack Overflow is full of idiots.",
        "description": "The Stack Overflow culture needs to be fixed. The overall gatekeeping & elitism in computer science & programming - as a whole ...",
        "thumbnails": {
          "default": {
            "url": "https://i.ytimg.com/vi/I_ZK0t9-llo/default.jpg",
            "width": 120,
            "height": 90
          },
          "medium": {
            "url": "https://i.ytimg.com/vi/I_ZK0t9-llo/mqdefault.jpg",
            "width": 320,
            "height": 180
          },
          "high": {
            "url": "https://i.ytimg.com/vi/I_ZK0t9-llo/hqdefault.jpg",
            "width": 480,
            "height": 360
          }
        },
        "channelTitle": "ForrestKnight",
        "liveBroadcastContent": "none",
        "publishTime": "2021-03-01T18:15:13Z"
      }
    },
    {
      "kind": "youtube#searchResult",
      "etag": "RwmGP1qMzUCzK6oV82s0NUEOETw",
      "id": {
        "kind": "youtube#video",
        "videoId": "sMIslcynm0Q"
      },
      "snippet": {
        "publishedAt": "2021-03-07T16:00:13Z",
        "channelId": "UCXwjZTvpFiBl93ACCUh1NXQ",
        "title": "How To Use Stack Overflow (no, ForrestKnight, it's not full of idiots)",
        "description": "Hey everyone, I can't believe I have to make this video. Unfortunately ForrestKnight recently made a video saying Stack Overflow ...",
        "thumbnails": {
        ...
      

Edit2: I tried

JSONObject jsonObject = new JSONObject( rest.getForObject(url, Object.class, params));  

        JSONArray array = jsonObject.getJSONArray("items" );
        for(int i=0;i<array.length();i  ){
            JSONObject snippet =array.getJSONObject(i);   
            System.out.println(snippet.getJSONObject("snippet").get("title"));
        }
    

JSONObject["items"] not found.

Edit3: I also tried without Edit2 and just

JSONObject jsonObject = new JSONObject( rest.getForObject(url, Object.class, params));  
System.out.println(jsonObject);

No error and I was about to fetch data shown in Postman. But in console printed {}, meaning I might not have gotten the data and won't be able to extract.

I tried extracting using .get System.out.println(jsonObject.get("items")); and I got the same error JSONObject["items"] not found.

Seems like it could be a format error, again it looks like json already and to use .get, I placed it inside jsonObject but found nothing

Edit4: I can confirm the data I get back is Json (like it says on the doc) using

try {
    new JSONObject(rest.getForObject(url, Object.class, params));
} catch (JSONException ex) {
    // edited, to include @Arthur's comment
    // e.g. in case JSONArray is valid as well...
    try {
        new JSONArray(rest.getForObject(url, Object.class, params));
    } catch (JSONException ex1) {
        return false;
    }
}
return true;

Returned true

Edit5: Seems like the keys is null after trying

String[] keys = JSONObject.getNames(jsonObject);

// iterate over them
for (String key1 : keys) {
    // retrieve the values
    Object value = jsonObject.get(key1);
    // if you just have strings:
    String value1 = (String) jsonObject.get(key1);
    System.out.println(value);
    System.out.println(value1);
}

Cannot read the array length because "keys" is null

CodePudding user response:

The RestTemplate delegates to the underlying Jackson to deserialize the JSON string to a java object .If you get the HTTP response as a generic object type , it will deserialize it into a Map.

You can simply create a POJO with the structure that is the same as the expected JSON response, and then use the Jackson annotations to configure how to deserialize the JSON into this POJO , and get the HTTP response as this POJO class.

Something like :

public class Result {

  @JsonProperty("items")
  private List<Item> items = new ArrayList<>();
    
}


public class Item {
    @JsonProperty("kind")
    private String kind;
    
    @JsonProperty("etag")
    private String etag;

    @JsonProperty("snippet")
    private List<Snippet> snippets = new ArrayList<>();
     
}


public class Snippet {

  @JsonProperty("channelId")
  private String channelId;

  @JsonProperty("title")
  private String title;
    
}

Then use the following to get the response :

Result result = rest.getForObject(url, Result.class, params);  

Once you get the Result POJO , use the favourite library to serialize it into XML.

P.S I just show you the ideas. You have to fine tune the POJO structure

  • Related