- Option 1 ( less preferred) Create a custom JSON serializer using reflection (if possible). I would need to have access to the field names of the class in order to do that. As far as I saw from the documentation it is possible to use reflection to do so https://teavm.org/docs/runtime/java-classes.html.
With reflection it won't be possible, because currently annotations aren't supported on fields and methods.
- Option 2 Use TeaVMs JSON parser in order to stringify the created JSObject (RpcRequest).
When I try option 2 I get some unexpected results (check screenshot of chrome inspector). I create an instance of RpcRequest, which implements JSObject and write it to object1 variable. As you can see I get extra data, the $id$ field and also every other fields gets a $ prefix. After using JSON.stringify on the object I get the value stored in jsontest2, which is quite different from what I envision from a serialized result of my object.
public interface RpcRequest extends JSObject { @JSProperty("jsonrpc") void setJsonRpc(String value); // etc } var rpcRequest = JSObjects.<RpcRequest>create(); rpcRequest.setJsonRpc("system_name");
Now I have a different issue. When trying to access class fields via TClass.getDeclaredField(String) I always get a null vlaue for the getter and setter. I've tried the following:
PS. I haven't done anything related to opening up reflection as noted here https://teavm.org/docs/runtime/java-classes.html. Would that be required?
var rpcRequest = JSObjects.<RpcRequest>create();
rpcRequest.setJsonRpc("system_name");"
I had gotten it to work in the way you mentioned by using JSObjects. However, I still can't grasp how to get constructor initialization to work as stated in the docs:
Previously, to declare a constructor for a JS class, you had to define static factory method, annotated with @JSBody and some JS within. Now, it's possible to declare a non-abstract overlay class (should be additionally annotated with @JSClass) with constructors. To instantiate such classes, you can use new syntax, as you used for normal Java classes.
Sorry, read again. You just cited my code. Please, don't use classes, don't use @JSClass, nor any of approaches you suggested in this topic. Use following approach to create and fill empty JS objects:
var rpcRequest = JSObjects.<RpcRequest>create(); rpcRequest.setJsonRpc("system_name");"
Actually, you don't even need to declare RpcRequest. It's just for having strongly typed interop with JS, but you can still write as follows:
var rpcRequest = JSObject.<JSMapLike<JSObject>>create(); rpcRequest.set("jsonrpc", JSString.valueOf("system_name"));
Trying to instantiate like so in a different java class ends up with a "RpcRequest is not defined". What am I missing here?
What you written can be read as follows: "there's an RpcRequest
class somewhere in JS runtime, here's it's description for Java".
Since there's no RpcRequest class in the browser, you get runtime
exception.
TeaVM call the classlib files by itself. Indeed it seems to work weirdly with JSO. JSClass jsClass = (JSClass) getPlatformClass().getMetadata(); always returns a JSWrapper.
Sure. JS objects are not really Java objects. For example, if we
have a JavaScript class like HTMLElement, there would no be any
Java description for it anywhere, since browser itself does not
know anything about Java. TeaVM does its best to somehow
emulate this for you, but still the perfect emulation is either
hard to implement or literally impossible.
If I understand correctly in order to make use of reflection I need to implement what's mentioned in the Tuning java class library and use it only with non JSO objects. --Right, but it still won't work with JSO.
Now, it's possible to declare a non-abstract overlay class (should be additionally annotated with @JSClass) with constructors
"Sorry, read again. You just cited my code. Please, don't use classes, don't use @JSClass, nor any of approaches you suggested in this topic. Use following approach to create and fill empty JS objects"
I see what you mean, but isn't the idea behind what I quoted from the docs to be able to substitute JSObjects.<RpcRequest>create(); + setters with the use of java constructors?
I just don't follow your mental model, sorry.
Now, it's possible to declare a non-abstract overlay class (should be additionally annotated with @JSClass) with constructorsIf I understand things correctly an "overlay" is a java representation of a JS class. We can declare it via an interface, memberless abstract class or since 0.10.0 via a non-abstract class annotated with @JSClass, which has a constructor (not sure about member fields). Your JSObjects solution works perfectly, I just want to understand the new constructor part.
It's about JavaScript classes with constructors. For example, Promise has constructor, but prior 0.10
it was impossible to declare it as a constructor, a static method
annotated with @JSBody should be
declared instead
This should conform with the new changes in 0.10.0@JSClass
public class RpcRequest implements JSObject {
public RpcRequest() {
}
@JSProperty
public native JSString getJsonrpc();
@JSProperty
public native void setJsonrpc(JSString jsonrpc);
@JSProperty
public native JSString getMethod();
@JSProperty
public native void setMethod(JSString method);
@JSProperty
public native JSMap<JSString, JSObject> getParams();
@JSProperty
public native void setParams(JSMap<JSString, JSObject> params);
@JSProperty
public native int getId();
@JSProperty
public native void setId(int id);
}
If you have your own hand-written JavaScript code that you load prior to TeaVM-generated JS and which contains something like
class RpcRequest { jsonrpc method params id constructor() { } }
Then yes, this should work.
RpcRequest request = new RpcRequest();
request.setJsonrpc(JSString.valueOf("2.0"));
request.setParams(new JSMap<>());
request.setId(1);
request.setMethod(JSString.valueOf("system_chain"));
Maybe I understand this wrong and the ctors are only accessible if you import the class inside of a JS file and use the constructor from there.
This depends on what you was going to do, but since I don't follow you mental model, I can't give a hint.