3

I know from https://stackoverflow.com/a/20445493/2848676 that the following code gives the error type mismatch cannot convert from element type object to string:

ArrayList objectArray = new ArrayList();
for (String str : objectArray) {

The compiler is giving me a warning in my declaration of objectArray that says ArrayList is a raw type. References to generic type ArrayList<E> should be parameterized. This all makes perfect sense to me. The fix is to specify the generic types:

ArrayList<String> stringArray = new ArrayList<String>();
for (String str : stringArray) {

This avoids the compiler warning and the compilation error.

My problem though is I'm trying to iterate over a subclass of ArrayList called org.json.simple.JSONArray and I don't have control over how the JSONArray is instantiated. Consequently I don't see the compiler warning anywhere but I do get the compilation error in this for loop line of code:

JSONArray insights = (JSONArray)jsonResult.get("insights");
for (JSONObject insightGroup : insights) {

I know I can work around this like this:

JSONArray insights = (JSONArray)jsonResult.get("insights");
for (int i=0; i<insights.size(); i++) {
    JSONObject insightGroup = (JSONObject) insights.get(i);

But can someone explain the finer points of generic types? In particular, how can the org.json.simple.JSONArray be instantiated without specifying the generic types? Is org.json.simple.JSONArray just poorly designed? Or am I not using the org.json.simple.JSONArray correctly?

Community
  • 1
  • 1
Michael Osofsky
  • 11,429
  • 16
  • 68
  • 113
  • 1
    Imagine that you want to use JSON with a legacy application that is running under java 1.4. Now, try to resolve generics with java 1.4. Backwards compatibility is a potential reason; I don't know if it is the reason. – DwB Nov 14 '14 at 18:40

2 Answers2

3

Is org.json.simple.JSONArray just poorly designed?

In my opinion, yes, but not for the reason you've described.

A JSON array can contain any JSON value type, not just JSON objects. So

for (JSONObject insightGroup : insights) {

should not be allowed, and isn't. The JSONObject type represents a JSON object. But the JSONArray can contain String values, other JSONArray values, numerical values, null, or other JSONObject values.

The JSON format is described here.

Maybe that is the reason that JSONArray was implemented as extending and implementing raw List types, which is typically not a good idea.

Community
  • 1
  • 1
Sotirios Delimanolis
  • 274,122
  • 60
  • 696
  • 724
  • I think I just found how JSON Simple (i.e. org.json.simple) was intended to be used. There is a (`ContainerFactory`)[https://code.google.com/p/json-simple/wiki/DecodingExamples#Example_4_-_Container_factory] that allows you to specify classes in the (Java Collections Framework)[http://docs.oracle.com/javase/7/docs/technotes/guides/collections/index.html]. And, "If you don't specify a container factory, org.json.simple.JSONObject is used for a Map and org.json.simple.JSONArray is used for a List." – Michael Osofsky Mar 23 '15 at 17:11
2

Yeah, looks like JSONArray is an ArrayList<Object> under the covers. Try creating an ArrayList<JSONObject>, something like this:

// The json-simple way
ArrayList<JSONObject> jsonThings = (JSONArray)JSONValue.parse(jsonString);
for (JSONObject j : jsonThings) {
    System.out.println("This is it:  " + j.toJSONString());
}

Or cast all over the place like this:

for (Object j : jsonThings) { 
    System.out.println("This is it:  " + ((JSONObject)j).toJSONString());
}
jgrim
  • 71
  • 3