0

I want to achieve that I override one method in JSONObject. So it always return a list even if it has one element:

import java.util.ArrayList;
import java.util.List;

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

public class JSONObjectDecorator extends JSONObject {

    public JSONObjectDecorator(JSONObject jsonObject) {
        super(jsonObject, JSONObject.getNames(jsonObject));
    }

    @Override
    public List<String> get(String field){
        List<String> result = new ArrayList<String>();
        if (!isNull(field)) {
            Object data = get(field);
            if (data instanceof JSONArray) {
                JSONArray array = (JSONArray) data;
                for (int i=0; i< array.length(); i++){
                    result.add(array.getString(i));
                }
            } else {
                result.add(data.toString());
            }
        }
        return result;
    }    

}

Right now this code gives a StackOverflowError because of this line:

Object data = get(field);

How should I achieve this?

UPDATE: I know why it is a StackOverflowError, and as @Andy Turner highlighted super.get solves the constructor issue, but then when I call for example getString() on an instance of the JSONObjectDecorator it throws an exception that the field is not String. (because it is the List, probably "getString" calls "get")

I will check where "get(String field)" called in JSONObject and I think solution will be to override those methods too.

Balazs Varhegyi
  • 991
  • 1
  • 18
  • 37
  • Use `super.get(field)` to call the superclass' implementation, rather than `get(field)`. Otherwise you're just invoking the same method again and again. – Andy Turner Jul 18 '16 at 08:35
  • thank you, yeah, figured out that in the meanwhile, but then my problem is that when I call for example getString() on an instance of the JSONObjectDecorator it throws an exception that the field is not String. (because it is the List, probably "getString" calls "get") – Balazs Varhegyi Jul 18 '16 at 08:40
  • The problem that you have here is that all of the `getSomething` methods are implemented in terms of the `Object get(String)` method; you are breaking the expectations of those methods. It is sort of the inverse of the [Fragile Base Class problem](https://en.wikipedia.org/wiki/Fragile_base_class): you are breaking the *base class* by changing the *subclass*, rather than the other way round. In fact, this is a basic deficiency in the design of the `JSONObject` class: `get` should really be final, since it is not well-designed to be overridden. Do this with composition, not inheritance. – Andy Turner Jul 18 '16 at 08:49
  • See *Effective Java 2nd Ed* Item 17: "Design and document for inheritance or else prohibit it". In particular, `org.json.JSONObject` does not document its self-use of the overridable `get` method. – Andy Turner Jul 18 '16 at 08:53
  • If I do it with composition I will need to write all the methods of JSONObject like: public String getString(String key){ return delegate.getString(key); }; except for "get(String key)", I want to avoid that. But now I'm not sure this composition is better OR the inheritance and override the broken methods like: public String getString(String key){ Object object = this.get(key).get(0); if (object instanceof String) { return (String) object; } throw new JSONException("JSONObject[" + quote(key) + "] not a string."); } – Balazs Varhegyi Jul 18 '16 at 09:09
  • You are subverting the expectations of code depending upon the "usual" behaviour of the `get` method - both through direct usages in client code and indirect usages like `getString`. As far as I understand the `JSONObject` class, *no method is expected to return a `List`*: because of this, the chains of `instanceof` checks in all client code won't ever check for a `List`, thus you will break - silently or otherwise - any such code. – Andy Turner Jul 18 '16 at 09:15
  • thank you Andy for the help, after all I use composition and delegate the methods I call from client code. It's sufficient enough for my case – Balazs Varhegyi Jul 18 '16 at 10:14

0 Answers0