0

I'm new to Java/JSON. My code adapting speech-android-wrapper. My this.sConfig.keywords is a public String[]. I know this toString() messed up with passing this.sConfig.keywords, but how to pass it correctly? I got error: "error": "Required type for parameter \"keywords\" is list. Got type unicode instead." Thanks!

 private void sendSpeechHeader() {

     JSONObject obj = new JSONObject();
     try {
         obj.put("action", "start");
         obj.put("content-type", this.sConfig.audioFormat);
         obj.put("interim_results", true);
         obj.put("continuous", true);
         obj.put("inactivity_timeout", this.sConfig.inactivityTimeout);
         obj.put("word_confidence", true); 
         obj.put("keywords_threshold", this.sConfig.keywordsThreshold); 
         obj.put("keywords", Arrays.toString(this.sConfig.keywords)); //this.sConfig.keywords is a  public String[]
     } catch (JSONException e) {
         e.printStackTrace();
     }
     String startHeader = obj.toString(); //I know this toString() messed up with passing this.sConfig.keywords, but how to pass it correctly?

     this.upload(startHeader);
     this.encoder.onStart();
     Log.d(TAG, "Sending init message: " + startHeader);
 }

Got error: 05-29 16:25:53.078 28782-29008/com.ibm.watson.developer_cloud.android.examples D/MainActivity: onMessage, message: { "error": "Required type for parameter \"keywords\" is list. Got type unicode instead."

ykcadcg
  • 73
  • 1
  • 10
  • Possible duplicate of [Java JsonObject array value to key](http://stackoverflow.com/questions/10704144/java-jsonobject-array-value-to-key) – Nikolay Shmyrev May 30 '16 at 11:21
  • btw the debugger for startHeader is this: {"action":"start","content-type":"audio\/ogg;codecs=opus","interim_results":true,"continuous":true,"inactivity_timeout":600,"word_confidence":true,"keywords_threshold":0.75,"keywords":"[banana, apple]"} – ykcadcg May 30 '16 at 17:32

1 Answers1

0

Was stuck for 1 day on this code:

     JSONObject obj = new JSONObject();
     obj.put("keywords", Arrays.toString(this.sConfig.keywords)); //****Problematic*****: this.sConfig.keywords is a  public String[]
 String startHeader = obj.toString(); //I know this toString() messed up with passing this.sConfig.keywords, but how to pass it correctly?
 this.upload(startHeader);

it gives error:

05-29 16:25:53.078 28782-29008/com.ibm.watson.developer_cloud.android.examples D/MainActivity: onMessage, message: {
                                                                                              "error": "Required type for parameter \"keywords\" is list. Got type unicode instead."

debugger shows startHeader as:

{"action":"start","content-type":"audio\/ogg;codecs=opus","interim_results":true,"continuous":true,"inactivity_timeout":600,"word_confidence":true,"keywords_threshold":0.5,"keywords":"[apple, banana, pear]"}

Solution is:

obj.put("keywords", new JSONArray(Arrays.asList( this.sConfig .keywords))); Source: Convert normal Java Array or ArrayList to Json Array in android

and the new debugger shows

{"action":"start","content-type":"audio\/ogg;codecs=opus","interim_results":true,"continuous":true,"inactivity_timeout":600,"word_confidence":true,"keywords_threshold":0.5,"keywords":["apple","banana","pear"]}

Reason for solution is:

The request needs a real list, not a flattened single string. So, "Arrays.toString" lost the list info and therefore didn't work. Directly obj.put("keywords", this.sConfig.keywords) won't work either because JSONObject.toString() won't understand the string array and translate that to a real list, and will only translate to the first address, and debugger shows "keywords":"[Ljava.lang.String;@51a0e2f".

The solution is using a real fixed-sized list to keep the string[] info, put it in JSONArray. Therefore the JSONObject.toString() will be able to keep the list structure.

Reference:

https://docs.oracle.com/javase/7/docs/api/java/util/Arrays.html#asList(T...) public static List asList(T... a)

Returns a fixed-size list backed by the specified array. (Changes to the returned list "write through" to the array.) This method acts as bridge between array-based and collection-based APIs, in combination with Collection.toArray(). The returned list is serializable and implements RandomAccess. This method also provides a convenient way to create a fixed-size list initialized to contain several elements: List stooges = Arrays.asList("Larry", "Moe", "Curly");

Lessons learned:

  1. think carefully about debugger's data structure, related it with error message, think what's expected (error message) and what's actual (debug info), then search online to find APIs that might lead to the expected.

  2. pure lack of experience for JSON. need to learn more about it.

Community
  • 1
  • 1
ykcadcg
  • 73
  • 1
  • 10