0

On the server side I format an object into Json using:

    String typeJson = new Gson().toJson(typeContainer);

On the client side I unwrap it using:

    JSONContainer<CommonNoun> typeContainer = new Gson().fromJson(result,
                             new TypeToken<JSONContainer<CommonNoun>>(){}.getType());

In execution, the thread never gets past the line above (I have a println right after it).

I've checked that the "result" string received by the client is the same as "typeJson" generated on the server. It looks like this:

{"myObject":{"cid":{"oid":129},"name":"technology","form":1},"children":[]}  

The 4 classes comprising the object being sent are:

public class JSONContainer<T> {

    private T myObject;
    private ArrayList<JSONContainer<T>> children;
    
    public JSONContainer() {

    }
    
    public JSONContainer(T anObject) {
        myObject = anObject;
        children = new ArrayList<JSONContainer<T>>();
    }
    
    public void addChildren(ArrayList<JSONContainer<T>> newChildren) {
        children.addAll(newChildren);
    }

    public void addChild(T concept) {
        children.add(new JSONContainer<T>(concept));
    }
        
    public ArrayList<JSONContainer<T>> getChildren() {
        return children;
    }
    
    public T getValue() {
        return myObject;
    }
    
    public boolean hasChildren() {
        if (children.size() > 0) return true;
        else return false;
    }
    
    public String toString() {
        return myObject.toString();
    }
}


public class CommonNoun extends Concept {
        
    /**
     * 
     */
    private static final long serialVersionUID = 6444629581712454049L;

    public CommonNoun() {
        super();
    }
    
    public CommonNoun(String name, ConceptID cidIn) {
        super(name, cidIn);
        this.form = ConceptDefs.COMMON_NOUN;
    }
    
}

public class Concept implements Serializable {
    
    /**
     * 
     */
    private static final long serialVersionUID = 2561549161503772431L;
    private ConceptID cid = null;
    private final String name;
    Integer form = 0;
    
//    ArrayList<ProperRelationship> myRelationships = null;

    
/*  @Deprecated
    public Concept(String name) {
        this.name = name;
    }*/
    
    public Concept() {
        name = "";
    }

    public Concept(String name, ConceptID cidIn) {
       // this(name);
        this.name = name;
        cid = cidIn;
    }

    /*
     * This should be over-ridden by any subclasses
     */
    public Integer getForm() {
        return form;
    } 
            
    public ConceptID getID() {
        return cid;
    }
    
    public void setID(ConceptID cidIn) {
        cid = cidIn;
    }
    
    //this doesn't make any sense.  Throw exception?
    public String getName() {
        return name;
    }

    public boolean isCommon() {
        return true;
    }
    
    /**
     *
     * @return
     */
    @Override
    public String toString() {
        return getName() + "(" + cid.toString() + ")";
    }
    
    public boolean equals(Concept other) {
        return ((getID().equals(other.getID())));
    }
       
}

public class ConceptID implements Serializable {

    long oid;
    
    public ConceptID() {
        oid = -1;
    }
    public ConceptID(long oid) {
        this.oid = oid;
    }
    
    public long getValue() {
        return oid;
    }
    
    /**
     *
     * @return
     */
    @Override
    public String toString() {
        return Long.toString(oid);
    }
    
    public Long toLong() {
        return Long.valueOf(oid);
    }

    
    public boolean equals(ConceptID other) {
        return (oid == other.getValue());
    }
    
    /**
     * Factory model for generating ConceptIDs
     * 
     * This one is here as a convenience as many IDs come in as a String from web POSTs
     * @param idAsString
     * @return
     */
    static public ConceptID parseIntoID(String idAsString) {
        ConceptID returnID = null;
        try {
            returnID = new ConceptID( Long.parseLong(idAsString) );
        } catch (Exception e) {
            System.err.println("Expected the string, " + idAsString + ", to be Long parsable.");
            e.printStackTrace();
        }
        return returnID;

    }
}

In my due-diligence to solve this, I worked to minimize the variables. Now I'm using the same json parser on both sides, and am writing the fromJson() statement in a way that doesn't produce a type warning when referring to the generics. I've studied the api for Gson (there are still combinations of GsonBuilder() left to exhaust), and I've searched StackOverflow and Google with terms such as "Gson" "Json" "parsing" "lock" "not complete." Prior to introducing my new generics class, I was experiencing success with using Gson to format and decompile json.

UPDATE:

After @ParanoidAndroid shared that parsing works in his environment, I tried to parse the json server-side, where it does work. So what's different about my server and client? The server project was generated by selecting one of the project wizard choices in Eclipse, and the client is a libGDX project. Another potential clue here is that libGDX implements its own class for json operations, called Json - was that done to address this situation?

Why aren't I using the native Json class? I started off that way, but could not get the formatting to match up. Json's is apparently non-standard, despite trying all the options available in setOutputType(OutputType).

How do I read this Generics correctly from JSON?

Next I tried to use Json server-side, but couldn't get the configuration to work: got as far as a ClassDefNotFound error.

One more variable I've controlled for is to copy and replace all of the classes being communicated through Json from the server to the client project to make sure everyone is using the same version (I'm sure there's some way to get projects to reference each other's classes, but I don't know it yet).

(final?) UPDATE:

Tried to create a thread dump as requested, but Java Mission Control wasn't having any of it.

Found documentation saying if I wanted to use the native Json class outside of libGDX, I should use jsonbeans: https://github.com/EsotericSoftware/jsonbeans/

Replaced my json serialization server-side with jsonbeans and can now use the native Json class client-side.

This is a poor answer to the question "Why doesn't this Gson parsing complete?":

"Because only the native Json parser works in some cases within libGDX. Furthermore, if you want that class to work with non-libGDX projects you better use it's companion class, jsonbeans."

  • What is the exception you are getting? – paranoidAndroid Aug 19 '20 at 20:09
  • There is no exception. The processing just never moves on from that line. I don't know what's really going on, but as far as information available goes it might as well be that the contents of that ~50 char json string is endlessly complex and the parsing can't be computed within our lifetimes. – RocketScienceGuy Aug 19 '20 at 20:33
  • System.out.println("result = " + result); JSONContainer typeContainer = new Gson().fromJson(result, new TypeToken>(){}.getType()); System.out.println("here I am."); ...I never see "here I am." in the console – RocketScienceGuy Aug 19 '20 at 20:36
  • Try taking a thread dump or pausing in the debugger to see where the thread is hanged. Something that can make the task hang is for example cyclic references between nodes (making the deserializer work on the same objects endlessly) - this is just an example - it cannot happen in this case because there are no children. – paranoidAndroid Aug 19 '20 at 20:36
  • I tried running your code on my machine and it works... – paranoidAndroid Aug 19 '20 at 20:43
  • I will figure out how to do a thread dump; thank you for pointing me to how to get more information. I've updated the question in response to the rest of your observations. – RocketScienceGuy Aug 19 '20 at 22:57

0 Answers0