Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Searching for a way to parse JSON Data to a Map #38

Closed
mirkosertic opened this issue Nov 25, 2014 · 13 comments
Closed

Searching for a way to parse JSON Data to a Map #38

mirkosertic opened this issue Nov 25, 2014 · 13 comments
Labels

Comments

@mirkosertic
Copy link
Contributor

Hi there

I am searching for a convenient way to read a JSON file from a specific URL and parse it to a Map. Are there some build in functions available, or do i have to use a JSON parser such as Gson?

Thanks in advance,
Mirko

@konsoletyper
Copy link
Owner

Hello! I can't answer your question without knowing what do you need exactly. I say no if you need something like Gson or Jackson, sinse TeaVM is a compiler, not a framework. Obviously, anyone can write a framework for parsing JSON. However, you can't reuse existing Gson or Jackson or whatever else, since they use reflection, which is unavailable in TeaVM. This limitation grows from the very nature of such transpilers, GWT has the same one. Both GWT and TeaVM have their own approach to metaprogramming, in GWT there are so called generators. Here is an example of a framework for GWT that parses JSON into POJOs according to Jackson annotations. Note that if you don't need to map JSON into POJOs and satisfied with JSON object model, you probably can reuse Gson or Jackson.

I say yes, if you are ok to deal with JavaScript directly. Remember, browser has its own way of parsing JSON. You can wrap it using JSO. However, the parsed JSON will be available as JSObject, which is very special.

@mirkosertic
Copy link
Contributor Author

Thank you for your quick reply! Basically i am reading a JSON file from a URL using XMLHttpRequest. Now i need to parse the JSON file to a simple Map. The org.json libraries are not working due to a missing JRE classes in the classlib. The provided GSon does also not compile due to missing classes.

Is there a code snipped available to show how to convert a JSON string to a Map? Either using some third party libraries or perhaps some build in magic?

@konsoletyper
Copy link
Owner

What do you mean when you say about converting JSON string to a Map? What if property value is not primitive? How should it be serialized?

With JSO you should do something like:

public interface JsonAPI extends JSObject {
    JSObject parse(String jsonString);
}

public interface JsonAPIProvider extends JSObject {
    @JSProperty("JSON")
    JsonAPI getJsonAPI();
}

public interface JsonMap {
    @JSIndexer
    JSObject get(String propertyName);
}

then use these interfaces:

JsonAPI json = ((JsonAPIProvider)JS.getGlobal()).getJsonAPI();
JsonMap map = (JsonMap)json.parse("{ \"foo\" : 23 }");
assert JS.unwrap(map.get("foo")) == 23;

Instead of JsonMap you can declare more meaningful JSObject with all required properties.

I don't know whether any JSON parser for Java is supported. AFAIK, there is no JSON parsing libraries written specially for TeaVM.

@mirkosertic
Copy link
Contributor Author

Well, basically i want to load a JSON file and store it as a map of maps, meaning every primitive will become also a primitive in the map, and every object will become another map.

I tried Gson and org.json libraries, but none of them compiled.

I will try JSO and try to wrap it with the java.util.Map interface...

@drxaos
Copy link

drxaos commented Nov 26, 2014

I used https://code.google.com/p/json-simple/ and it compiled to js.

@mirkosertic
Copy link
Contributor Author

I can confirm that json-simple compiles to js, but throws StringIndexOutOfBoundExceptions when compiled to JS with complex JSON files. The Java version seems to work.

I am working on a JSO implementation, but searching for a way to determine wether a JSObject is a JSArray or not. As documented, using instanceof is not recommended. Any ideas?

@konsoletyper
Copy link
Owner

@mirkosertic, do you use latest stable (0.2.1) or latest master (0.3.0-SNAPSHOT)? There were some problems with json-simple, but @drxaos provided patch for TeaVM.

To determine whether JSObject is JavaScript array, use JS.getType

@mirkosertic
Copy link
Contributor Author

I am using 0.2.1. JS.getType() only gives me OBJECT for objects. Are simple obejcts and arrays mapped to JSType.OBJECT, or are arrays mapped as JSType.FUNCTION?

@shannah
Copy link
Sponsor Contributor

shannah commented Nov 26, 2014

Distinguishing arrays from objects is a Javascript problem. This stack
overflow thread provides some suggestions (e.g. use Array.isArray()):
http://stackoverflow.com/questions/4775722/check-if-object-is-array

Steve

On Wed, Nov 26, 2014 at 11:46 AM, Mirko Sertic notifications@github.com
wrote:

I am using 0.2.1. JS.getType() only gives me OBJECT for objects. Are
simple obejcts and arrays mapped to JSType.OBJECT, or are arrays mapped as
JSType.FUNCTION?


Reply to this email directly or view it on GitHub
#38 (comment).

Steve Hannah
Web Lite Solutions Corp.

@konsoletyper
Copy link
Owner

Try to build the latest TeaVM from sources and json-simple will work better, I suppose. You can write your own JavaScript function like this:

function isArray(obj) {
    obj.constructor === Array;
}

and then wrap this function with JSO object. Or you can use the following snippets:

public interface ConstructedObject extends JSObject {
    @JSProperty
    JSObject getConstructor();
}
public interface Constructors extends JSObject {
    JSObject getArray();
}

and use these interfaces to check if object is an array:

return ((ConstructedObject)object).getConstructor() == ((Constructors)JS.getGlobal()).getArray();

@mirkosertic
Copy link
Contributor Author

Thanks for your response.

The following snipped seems to work:

public interface Constructors extends JSObject {

    @JSProperty("Array")
    JSObject getArray();
}

I've created a small JSON parser using my own code. Even with 0.3.0-SNAPSHOT and json-simple i am getting strage exceptions in StringBuilder class. But for now i am fine with my solution. Anyway it would be cool if json simple is working property in future releases.

@ivanceras
Copy link

Hi mirk,

I created this project gwt.reflection. I just recently open sourced it. Basically what it does it you can specify which classes you need to have reflection with and it will generate a code for you, which will be compiled together with your other GWT source code. It is heavily using a lot of conditional branching to execute appropriate methods/ return properties for each of classes which needs reflection. I admit, this is rather messy and prone to abuse and misuse, and also makes the compiled javascript a bit larger. This reflection capability was designed mainly for POJO's without special anotations required, so you can transform JSON back and forth to POJO.
As you can see in this code. It has a method that converts JSON from and to HashMap, but I didn't really heavily use this since, I was converting from the close representation of Object using POJO instead of generics(Maps). I can see that having the ability to convert for Maps will offer a more flexible use-case, but somehow loose the ability to chain the mapping/conversion of complex objects that contains complex objects, which also contains complex objects, etc.

@konsoletyper
Copy link
Owner

@ivanceras, there is already GWT Reflection. But generally it is better and easier to write your own generator instead of trying to bring reflection to GWT. With TeaVM I'll try to follow the same direction.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

5 participants