2017-08-14 23 views
2

Google Books APIを使用するAndroidアプリケーションを作成しました。 JSONレスポンスをサーバから取得すると、レスポンスを解析して、タイトル、著者、カテゴリ、パブリッシャ、ページ数、サムネイル、およびその書籍の詳細を取得します。問題は、JSONレスポンスの一部の書籍にサムネイルキーまたはカテゴリキーがないことです。 JSONのキー値を取得しようとすると、プログラムはエラーをスローし、エラーが発生した後に他の書籍を追加するコードをスキップします。異なるキーを使用したJSONオブジェクトの解析

私はネストされた try catchブロックで解決しました。たとえば、レスポンスにパブリッシャキーがない場合、nullを返します。私は私の構文解析を完了した後、私は私のビューを更新する必要が

private List<BookData> parseJsonResponse(String jsonResponse) { 
    List<BookData> bookData = new ArrayList<>(); 

    try { 
     JSONObject rootObject = new JSONObject(jsonResponse); 
     JSONArray itemsArray = rootObject.getJSONArray("items"); 
     for (int i = 0; i < itemsArray.length(); i++) { 
      JSONObject itemObject = itemsArray.getJSONObject(i); 
      JSONObject volumeInfo = 
       itemObject.getJSONObject("volumeInfo"); 

      String title; 
      try { 
       title = volumeInfo.getString("title"); 
      } catch (JSONException e) { 
       title = null; 
      } 

      ArrayList<String> authors; 
      try { 
       JSONArray authorsArray = 
        volumeInfo.getJSONArray("authors"); 
       authors = new ArrayList<>(); 
       for (int j = 0; j < authorsArray.length(); j++) { 
        authors.add(authorsArray.getString(j)); 
       } 
      } catch (JSONException e) { 
       authors = null; 
      } 

      ArrayList<String> categories; 
      try { 
       JSONArray categoriesArray = 
        volumeInfo.getJSONArray("categories"); 
       categories = new ArrayList<>(); 
       for (int k = 0; k < categoriesArray.length(); k++) { 
        categories.add(categoriesArray.getString(k)); 
       } 
      } catch (JSONException e) { 
       categories = null; 
      } 

      String publisher; 
      try { 
       publisher = volumeInfo.getString("publisher"); 
      } catch (JSONException e) { 
       publisher = null; 
      } 

      String publishedDate; 
      try { 
       publishedDate = 
        volumeInfo.getString("publishedDate"); 
      } catch (JSONException e) { 
       publishedDate = null; 
      } 

      int pageCount; 
      try { 
       pageCount = volumeInfo.getInt("pageCount"); 
      } catch (JSONException e) { 
       pageCount = 0; 
      } 

      String language; 
      try { 
       language = volumeInfo.getString("language"); 
      } catch (JSONException e) { 
       language = null; 
      } 

      String description; 
      try { 
       description = volumeInfo.getString("description"); 
      } catch (JSONException e) { 
       description = null; 
      } 

      String bookWebsite; 
      try { 
       bookWebsite = volumeInfo.getString("infoLink"); 
      } catch (JSONException e) { 
       bookWebsite = null; 
      } 

      Bitmap thumbnail; 
      try { 
       JSONObject imageLink = 
        volumeInfo.getJSONObject("imageLinks"); 
       String thumbnailUrl = 
        imageLink.getString("thumbnail"); 
       thumbnail = getThumbnailBitmap(thumbnailUrl); 
      } catch (JSONException e) { 
       thumbnail = null; 
      } 

      // Add a new BookData object to the list 
      bookData.add(new BookData(title, thumbnail, authors, 
         categories, publisher, publishedDate, 
         pageCount, language, description, 
         bookWebsite)); 
     } 
    } catch (JSONException e) { 
     Log.e(LOG_TAG, null, e); 
    } 
    return bookData; 
} 

:ここ

String publisher; 
    try { 
    publisher = volumeInfo.getString("publisher"); 
    } catch (JSONException e) { 
    publisher = null; 
    } 

は、JSON応答を解析するための全体の方法がどのように見えるかです。私はリストビューを使用しているので、アダプタはビューの膨張を処理する必要があります。 変数がnullでないかどうかを調べるためにifステートメントを追加しなければならなかった。例えば、テキストビューのテキストを設定する。それ以外の場合は、「Publisher not available」に設定します。

public class BookDataAdapter extends ArrayAdapter<BookData> { 

public BookDataAdapter(@NonNull Context context, @NonNull 
         List<BookData> bookDatas) { 
    super(context, 0, bookDatas); 
} 

@NonNull 
@Override 
public View getView(int position, @Nullable View convertView, 
        @NonNull ViewGroup parent) { 
    View listView = convertView; 
    if (listView == null) { 
     listView = LayoutInflater.from(getContext()) 
       .inflate(R.layout.book_list_item, parent, false); 
    } 
    // Get current BookData object 
    BookData bookData = getItem(position); 

    ImageView thumbnail = listView.findViewById(R.id.book_thumbnail); 
    if (bookData.getThumbnail() != null) { 
     thumbnail.setImageBitmap(bookData.getThumbnail()); 
    } else { 
     // Set default thumbnail 
     thumbnail.setImageResource(R.drawable.default_thumbnail); 
    } 

    TextView title = listView.findViewById(R.id.book_title); 
    if (bookData.getTitle() != null) { 
     title.setText(bookData.getTitle()); 
    } else { 
     title.setText("Title not available"); 
    } 

    TextView author = listView.findViewById(R.id.book_author); 
    if (bookData.getAuthors() != null) { 
     author.setText(listToString(bookData.getAuthors())); 
    } else { 
     author.setText("Authors not available"); 
    } 

    TextView category = listView.findViewById(R.id.book_category); 
    if (bookData.getCategories() != null) { 
     category.setText("Category: " + 
     listToString(bookData.getCategories())); 
    } else { 
     category.setText("Category not available "); 
    } 

    TextView publisher = listView.findViewById(R.id.book_publisher); 
    if (bookData.getPublisher() != null) { 
     publisher.setText(bookData.getPublisher() + ", "); 
    } else { 
     publisher.setText("Publisher not available, "); 
    } 

    TextView publishedDate = 
     listView.findViewById(R.id.book_published_date); 
    if (bookData.getPublishedDate() != null) { 
     publishedDate.setText(bookData.getPublishedDate()); 
    } else { 
     publishedDate.setText("Published date not available"); 
    } 

    TextView pageCount = listView.findViewById(R.id.book_page_count); 
    if (bookData.getPageCount() != 0) { 
     pageCount.setText("Pages: " + bookData.getPageCount()); 
    } else { 
     pageCount.setText("Page count not available"); 
    } 

    TextView language = listView.findViewById(R.id.book_language); 
    if (bookData.getLanguage() != null) { 
     language.setText(bookData.getLanguage()); 
    } else { 
     language.setText("Language not available"); 
    } 

    TextView description = 
     listView.findViewById(R.id.book_description); 
    if (bookData.getDescription() != null) { 
     description.setText(bookData.getDescription()); 
    } else { 
     description.setText("Description not available"); 
    } 
    return listView; 
} 

private String listToString(List<String> list) { 
    if (list == null || list.size() == 0) { 
     return null; 
    } 
    StringBuilder builder = new StringBuilder(); 
    for (int i = 0; i < list.size(); i++) { 
     builder.append(list.get(i)); 
     if (i == (list.size() - 1)) { 
      break; 
     } 
     builder.append(", "); 
    } 
    return builder.toString(); 
} 

}

そして最後に、私は質問をしたい:ここ

TextView publisher = listView.findViewById(R.id.book_publisher); 
    if (bookData.getPublisher() != null) { 
    publisher.setText(bookData.getPublisher()); 
    } else { 
    publisher.setText("Publisher not available"); 
    } 

は全体のアダプタがどのように見えるかです。ネストされたtry catchステートメントは良い方法ではないと言う人がいるので、異なるキーでJSONレスポンスを解析する方が良い方法や効率的な方法がありますか?

ありがとうございます!

答えて

1

あなたは2つのオプションがあります。

  1. .has()を使用して

    String publisher = null; 
    if(volumeInfo.has("publisher")){ 
        publisher = volumeInfo.getString("publisher"); 
    } 
    
  2. optの代わりに、get(より良い、IMO)の使用:プリミティブのオブジェクトに対するnull0/false

    String publisher = volumeInfo.optString("publisher"); 
    

opt###メソッドのデフォルトを、あなたは記述する必要はありませんtry/catchブロックまたはif条件。 2番目のパラメータをデフォルト値として指定することもできます。

String publisher = volumeInfo.optString("publisher", "no publisher"); 
// if publisher is not a valid key, "no publisher" will be returned 
+0

ありがとう、これは私の解析をはるかにクリーンな方法です。 –

+0

@VidBregar 2番目のオプションも好きです。きれいで、追加のコードは必要ありません。どういたしまして! – BackSlash

0

使用して、あなたはJSONObject

if(volumeInfo.has("publisher")){ 
    volumeInfo.getString("publisher"); 
} 
0

.has()財産あなたは、個々のtry/catchブロックでJSONの操作をラップする必要はありませんすることができます。

この問題に対処するために、JSONライブラリ内の方法があります:

jsonObject.isNull(key); 

あなたはそれがこのようにキーの書き込みにより値を取得しようとすると:

if (!volumeInfo.isNull("categories")) { 
    JSONArray categoryArray = volumeInfo.getJSONArray("categories"); 
} 
関連する問題