First of all do not use JSNI going forward.
Use elemental2 (or define your own JSON.parse):
Without elemental2:
@JsType(isNative=true, namespace = JsPackage.GLOBAL);
public class JSON {
public static Object parse(String s, Reviver r);
}
@JsFunction
public interface Reviver {
public Object run(String key, Object value);
}
// usage:
MyObject o = (MyObject) JSON.parse(s, (key, value) -> {
// whatever change you need to do
return value;
});
-Daniel
On Wed, May 10, 2017 at 9:53 AM <[email protected]> wrote:
>
> I am still new to GWT (so this code is probably naive), but I implemented
> this JSON parse wrapper which performs "transparent" conversion of JS
> arrays to java.util.List and using replacer/reviver functions:
>
> https://github.com/bpilot/jclosure/blob/master/src/main/java/ailabs/jclosure/client/encoding/json/JsonParser.java
>
> Could this be made more general?
>
>
> On Wednesday, May 10, 2017 at 11:40:53 AM UTC-4, Marcin Okraszewski wrote:
>>
>> I've done something that I think is so far the closest to what I want to
>> achieve - the same object behaving as List in Java and as array in JS.
>> Actually it can be seen in Java as either list or array - both work :-)
>>
>> First I declare JsArray:
>>
>> @JsType(isNative=true, name="Array", namespace=JsPackage.GLOBAL)
>> public class JsArray<E> {
>> // JS method declarations here, but can be also empty
>> }
>>
>>
>> Then extend create a List that extends the JsArray
>>
>> @JsType
>> public class JsArrayList<E> extends JsArray<E> implements List<E> {
>> // List implementation here
>> }
>>
>>
>> Now, parse JSON and replace arrays with instances of JsArrayList.
>>
>> private static native <T> T parse(String json) /*-{
>> return JSON.parse(json, function(key, value) {
>> if (Array.isArray(value)) {
>> var arrayList = new @interop.client.JsArrayList::new();
>> Array.prototype.push.apply(arrayList, value);
>> value = arrayList;
>> }
>> return value;
>> });
>> }-*/;
>>
>> Now, if the JSON includes any array, you will be able to use in Java as
>> List.
>>
>> Problems so far:
>>
>> 1. All elements of the array need to be copied. I was tempted to just
>> change __proto__ with the one from JsArrayList, but that is said to affect
>> performance. I could also add methods from JsArrayList to the instance,
>> not
>> sure if that is better from performance standpoint.
>> 2. The extended array is not recognized as an array in JS (although
>> it behaves as array). Array.isArray() returns false, same for instanceof
>> Array. I guess, adding functions to array instance would solve it.
>> 3. While parsing metadata are missing, what actual type should that
>> be. Switching arrays to list is a decision without context. But when we
>> want to treat an object as map, then it would need to be known somehow. It
>> can be naming convention of fields, but it is not perfect; could not
>> supported nested collections. Some meta provided from the interface that
>> is
>> being cased, would be great.
>>
>> Do you have any thoughts on that maybe?
>>
>> Thank you,
>> Marcin
>>
>>
>> On Wednesday, 10 May 2017 01:19:58 UTC+2, Ray Cromwell wrote:
>>>
>>> I think it would be better to use a JsArrayListAdapter in order to
>>> prevent making copies all over the place, and also making mutations
>>> write-through on both sides e.g.
>>>
>>> public class JsArrayListAdapter<T> extends AbstractList<T> {
>>> public JsArrayListAdapter(ArrayLike<T> blah) {
>>> this.array = blah;
>>> }
>>>
>>> // implement List methods to delegate to Array methods
>>> }
>>>
>>> To keep referential integrity, you need to use an expando or ES6 Symbol
>>> property to hide a backreference.
>>>
>>> That is, JsArrayListAdapter.wrap(nativeJsArray) ==
>>> JsArrayListAdapter.wrap(nativeJsArray2) IFF nativeJsArray == nativeJsArray2.
>>>
>>> This technique is less error prone IMHO if you are going to have mutable
>>> objects. If you're using immutables, then making copies is superior.
>>>
>>>
>>>
>>>
>>>
>>> On Tue, May 9, 2017 at 3:24 PM 'Goktug Gokdogan' via GWT Contributors <
>>> [email protected]> wrote:
>>>
>>>> Yes, theoretically you should be able to use the second parameter on
>>>> Json.parse Json.stringify for conversion back and forth between java
>>>> collections and js primitives. In this model, your javascript code needs to
>>>> use Java collection APIs.
>>>>
>>>> > java.util.Arrays.asList() should be enough
>>>>
>>>> keep in mind that Arrays.asList won't let you go out of bounds.
>>>>
>>>>
>>>>
>>>> > I believe it was in plans with @JsConvert
>>>>
>>>>
>>>> We are not working on @JsConvert right now. JsConvert is just
>>>> convenience and you can mimic it:
>>>>
>>>>
>>>> @JsType(isNative=true)
>>>> interface MyType {
>>>> @JsConvert(ListConverter.class)
>>>> List getMyArray()
>>>> void setMyArray(@JsConvert(ListConverter.class) List array)
>>>> }
>>>>
>>>> is roughly equivalent to:
>>>>
>>>> @JsType(isNative=true)
>>>> interface MyType {
>>>> @JsProperty(name="myArray")
>>>> Object[] getMyArrayInternal();
>>>>
>>>> @JsOverlay
>>>> default List getMyArray() { return Arrays.asList(getMyArray()); }
>>>>
>>>> @JsProperty(name="myArray")
>>>> void setMyArrayInternal(Object[] array);
>>>>
>>>> @JsOverlay
>>>> default void setMyArray(List list) {
>>>> setMyArrayInternal(array.toArray());
>>>> }
>>>> }
>>>>
>>>>
>>>> On Tue, May 9, 2017 at 9:32 AM, Thomas Broyer <[email protected]>
>>>> wrote:
>>>>
>>>>>
>>>>>
>>>>> On Tuesday, May 9, 2017 at 4:34:48 PM UTC+2, Marcin Okraszewski wrote:
>>>>>>
>>>>>> There is indeed something in it. Actually you could have some type of
>>>>>> naming convention, like in TJSON (
>>>>>> https://tonyarcieri.com/introducing-tjson-a-stricter-typed-form-of-json)
>>>>>> or TypedJson (https://www.npmjs.com/package/typed-json) to figure
>>>>>> out proper types. But then I would need to create eg. ArrayList with the
>>>>>> Manuel's trick (the asList() from Polymer). I'll test it.
>>>>>>
>>>>>
>>>>> java.util.Arrays.asList() should be enough actually:
>>>>> https://github.com/gwtproject/gwt/blob/2.8.1/user/super/com/google/gwt/emul/java/util/Arrays.java#L136
>>>>> (note that the ArrayList there is not java.util.ArrayList, it's an
>>>>> internal
>>>>> java.util.Arrays.ArrayList class that directly wraps the array with no
>>>>> copy).
>>>>>
>>>>> --
>>>>> You received this message because you are subscribed to the Google
>>>>> Groups "GWT Contributors" group.
>>>>> To unsubscribe from this group and stop receiving emails from it, send
>>>>> an email to
>>>>> [email protected].
>>>>> To view this discussion on the web visit
>>>>> https://groups.google.com/d/msgid/google-web-toolkit-contributors/95e1bd43-b4a6-4b2d-bd89-6cc6fb206631%40googlegroups.com
>>>>> <https://groups.google.com/d/msgid/google-web-toolkit-contributors/95e1bd43-b4a6-4b2d-bd89-6cc6fb206631%40googlegroups.com?utm_medium=email&utm_source=footer>
>>>>> .
>>>>>
>>>>> For more options, visit https://groups.google.com/d/optout.
>>>>>
>>>>
>>>> --
>>>> You received this message because you are subscribed to the Google
>>>> Groups "GWT Contributors" group.
>>>> To unsubscribe from this group and stop receiving emails from it, send
>>>> an email to
>>>> [email protected].
>>>> To view this discussion on the web visit
>>>> https://groups.google.com/d/msgid/google-web-toolkit-contributors/CAN%3DyUA0Wr0pWKUcqyN2YMkuoZZK7b3e-ipm7jqv2DdDeqk8sMA%40mail.gmail.com
>>>> <https://groups.google.com/d/msgid/google-web-toolkit-contributors/CAN%3DyUA0Wr0pWKUcqyN2YMkuoZZK7b3e-ipm7jqv2DdDeqk8sMA%40mail.gmail.com?utm_medium=email&utm_source=footer>
>>>> .
>>>> For more options, visit https://groups.google.com/d/optout.
>>>>
>>> --
> You received this message because you are subscribed to the Google Groups
> "GWT Contributors" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> To view this discussion on the web visit
> https://groups.google.com/d/msgid/google-web-toolkit-contributors/651f6423-853c-4c25-9b92-86d8ab711067%40googlegroups.com
> <https://groups.google.com/d/msgid/google-web-toolkit-contributors/651f6423-853c-4c25-9b92-86d8ab711067%40googlegroups.com?utm_medium=email&utm_source=footer>
> .
> For more options, visit https://groups.google.com/d/optout.
>
--
You received this message because you are subscribed to the Google Groups "GWT
Contributors" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/google-web-toolkit-contributors/CALLujiqSp_pBbowhNtE5230O%3DSmY93Uphjpy3Ca_q_H0y8ymMA%40mail.gmail.com.
For more options, visit https://groups.google.com/d/optout.