1

I am trying to make a dictionary application using Oxford Dictionary api. There is something wrong with my code JSON. Can anyone tell me how do I extract only the definition of the searched word, rather getting the whole JSON file

import android.os.AsyncTask;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;

import com.squareup.okhttp.Callback;
import com.squareup.okhttp.OkHttpClient;
import com.squareup.okhttp.Request;
import com.squareup.okhttp.Response;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;

import javax.net.ssl.HttpsURLConnection;


public class MainActivity extends AppCompatActivity {

    private static final String APP_ID= "59028fc6";
    private static final String API_KEY = "ad3e310307d7b2f8bf474c45e1efd01f";

    private static final String TAG = MainActivity.class.getSimpleName();

    private OkHttpClient okHttpClient;

    private EditText textInput;
    private Button submitButton;
    private TextView definitionView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // initialize ok http
        okHttpClient = new OkHttpClient();

        textInput = findViewById(R.id.textInput);
        submitButton = findViewById(R.id.submitButton);
        definitionView = findViewById(R.id.textMeaning);

        submitButton.setOnClickListener(
                new View.OnClickListener() {
                    @Override
                    public void onClick(View view) {
                        findMeaningOfEnteredWord();
                    }
                });
    }

    private void findMeaningOfEnteredWord() {
        String word = textInput.getText().toString();
        if (word.isEmpty()) {
            Toast.makeText(this, "Nothing entered", Toast.LENGTH_SHORT).show();
            return;
        }

        // create url from the word
        String lowerCaseWord = word.toLowerCase();
        String httpRequestUrl = "https://od-api.oxforddictionaries.com:443/api/v1/entries/en/" + lowerCaseWord;
        // make request with REST url
        new RequestAsyncTask().execute(httpRequestUrl);
    }

    private class RequestAsyncTask extends AsyncTask<String, Integer, String> {

        @Override
        protected String doInBackground(String... params) {
            String requestUrl = params[0];
            Request request = new Request.Builder()
                    .url(requestUrl)
                    .addHeader("Accept", "application/json")
                    .addHeader("app_id", APP_ID)
                    .addHeader("app_key", API_KEY)
                    .build();

            Response response = null;
            try {
                response = okHttpClient.newCall(request).execute();
                return response.body().string();
            } catch (IOException ex) {
                Log.e(TAG, "caught error: " + ex.getMessage());
            }

            return "";
        }

        @Override
        protected void onPostExecute(String result) {
            try {
                JSONObject responseAsJson = new JSONObject(result);
                JSONArray results = responseAsJson.getJSONArray("results");
                if (results.length() > 0) { // valid definitions were found
                    String lexicalEntries = results.getJSONObject(0).getString("lexicalEntries");
                    definitionView.setText(lexicalEntries);

                }

                Log.d(TAG, " " + responseAsJson.toString());
            } catch (Exception ex) {
                Log.d(TAG, "exception during json parsing: " + ex.getMessage());
            }


        }
    }
}

JSON:

{"id":"aeroplane",
"language":"en",
"lexicalEntries": [
    {
    "entries": [{"etymologies":["late 19th century: from French aéroplane, from aéro- ‘air’ + Greek -planos ‘wandering’"],
    "grammaticalFeatures":[{"text":"Singular","type":"Number"}],
         "homographNumber":"000",
          "senses":[{"crossReferenceMarkers":["North American term airplane"],
           "crossReferences":[{"id":"airplane","text":"airplane","type":"see also"}],
         "definitions":["a powered flying vehicle with fixed wings and a weight greater than that of the air it displaces."],
         "domains":["Aviation"],
       "id":"m_en_gbus0013220.005",
       "regions":["British"],
       "short_definitions":["powered flying vehicle with fixed wings"],

    "thesaurusLinks":[{"entry_id":"plane","sense_id":"t_en_gb0011151.001"}]}]}],"language":"en","lexicalCategory":"Noun","pronunciations":[{"audioFile":"http:\/\/audio.oxforddictionaries.com\/en\/mp3\/aeroplane_gb_2.mp3","dialects":["British English"],"phoneticNotation":"IPA","phoneticSpelling":"ˈɛːrəpleɪn"}],"text":"aeroplane"}],
"type":"headword","word":"aeroplane"

}
Phantômaxx
  • 37,901
  • 21
  • 84
  • 115
Flavy
  • 11
  • 2

3 Answers3

1

Modify these lines :

String lexicalEntries = results.getJSONObject(0).getString("lexicalEntries");
definitionView.setText(lexicalEntries);

to :

String definition = results.getJSONObject(0).getString("lexicalEntries")
.getJSONArray("entries").getJSONObject(0).getJSONArray("senses")
.getJSONObject(0).getJSONArray("definitions").getString(0);
definitionView.setText(definition);

Of course you may need to modify your UI based on the number of definitions a word has.

Also, you should probably consider using POJOs instead of directly dealing with the JSON response. I'd recommend Jackson or GSON for doing this.

Community
  • 1
  • 1
Neeraj
  • 2,376
  • 2
  • 24
  • 41
1
  String definitions=results.getJSONArray("lexicalEntries")
                       .getJSONObject(0)
                       .getJSONArray("entries")
                       .getJSONObject(0)
                       .getJSONArray("senses")
                       .getJSONArray("definitions")
                       .get(0)
kfir88
  • 380
  • 2
  • 16
0

So , The thing is , There are a lot of gaps in the JSON for different words . Which means a word may have an array of "synonyms" but others don't , So in your code you are trying to reach something that doesn't actually exist (a NULL value) which is likely to throw an exception every time you search for a word that the JSON returned doesn't match the JSON you are expecting , Because there are missing (NULL) values . The app I made using oxford dictionary required a lot of work just to make sure there is no thrown exception . I used retrofit with moshi converter factory , And then Do the following :

1-In your custom classes , Make sure you annotate every data member with @Json and provide the name of the keys in the JSON of oxford

2-make sure that every declared type is nullable , including both List and the type inside of it

You'll then be able to get the result , And Now comes the part where you handle evey call that may be null

I know this is a bit old question , But It happened that I struggled with this api once , So I hope this may help someone :)