Thanks for hint. Indeed, it is the same concept here. The only difference in parser is that I targeted in a List implementation that would still work as array in JS, so I can share exactly the same model between JS and GWT. I also plan to use JsInterop to access objects, while I see overlay types are used here, which would make it more difficult to share with server; but again conceptually is same.
Thanks you, Marcin On Wednesday, 10 May 2017 18:53:06 UTC+2, [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/7ad1c156-af43-4f40-bdfd-ae5d4839e259%40googlegroups.com. For more options, visit https://groups.google.com/d/optout.
