How to create typed Sequential dynamically in runtime?

59 views
Skip to first unread message

Oleg Neklyudov

unread,
Oct 26, 2016, 7:48:25 PM10/26/16
to ceylon-users
Hello!

I am working on JSON mapper for Ceylon (https://github.com/ceylonforge/jsonmapper), using ceylon metamodel.

I have already implemented some basic stuff, but I have problem with mapping nested JSONn arrays into object attributes.

For example, I need to implement this test:
-----
        checkLoad(`DummyArraySequential<DummyInteger>`, """{"items":[{"int":111}, {"int":222}]}""",
            "DummyArraySequential{items=[DummyInteger{int=111}, DummyInteger{int=222}]}");

class DummyArraySequential<T>(T[] items) {
    shared actual String string => classname(this) + "{items=``items``}";
}
class DummyInteger(Integer int) {
    shared actual String string => classname(this) + "{int=``int``}";
}
-----

I've implemented function to map JsonObject into DummyInteger: Anything resolveValue<Target>(Value jsonValue, Type<Target> targetType)
But how to build dynamically typed Sequential object (that satisfies Sequential<DummyInteger> in our case) in this function: Anything resolveSequential(JsonArray jsonValue, ClassOrInterface<Sequential<>> targetType) ?
(function have to return this sequential object and caller pass it into constructor of DumyArraySequential).

Or maybe this approach with JSON mapper is totaly wrong at all and there is another idiomatic ceylonic way to do JSON mapping/build such library?

---
Oleg Neklyudov

Lisi

unread,
Oct 27, 2016, 2:57:24 AM10/27/16
to ceylon-users
Looks like serialization / deserialization. See:

In any case I think you can instantiate sequential as usual: `[for(descriptor in descriptors) instantiate(descriptor)]` something like this.


четверг, 27 октября 2016 г., 3:48:25 UTC+4 пользователь Oleg Neklyudov написал:

Tako Schotanus

unread,
Oct 27, 2016, 6:12:56 AM10/27/16
to ceylon-users
Hi Oleg,

you could perhaps create an `Array<DummyInteger>` (ceylon.language.Array, not ceylon.json.Array), fill that with the needed objects and then call `.sequence()` on it?
That will get you the required `Sequential<DummyInteger>` as you wanted.

HTH


-Tako

--
You received this message because you are subscribed to the Google Groups "ceylon-users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ceylon-users+unsubscribe@googlegroups.com.
To post to this group, send email to ceylon...@googlegroups.com.
Visit this group at https://groups.google.com/group/ceylon-users.
To view this discussion on the web visit https://groups.google.com/d/msgid/ceylon-users/12967ec3-550a-4843-8ae1-1f8b94f4e801%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Oleg Neklyudov

unread,
Oct 27, 2016, 5:40:08 PM10/27/16
to ceylon-users, ta...@codejive.org
Hi Tako,
Hi Lisi.

Thank you for advices!

I already tried an approach with Array - the problem with it that there is no compile-type information about generic types argument (only runtime - I build generally applicable library, example code is from unit tests) - after several attempts with metamodel manipulation I have fail to build correct typed solution around Array (there is runtime type check error in one or another point of code).

Comprehension doesn't work directly too because of lack of compile time type information for generics arguments. In my case comprehension result type is Sequential<Anything> which is not assignable to Sequential<DummyInteger> (runtype type check error).

But it seems, that I found solution (I am coding it right now - it will be available on github soon, I hope):

1) I have created fully typed method (its counterpart resolveType returns Anything)
Target resolveValueTyped<Target>(Value jsonValue, Type<Target> targetType) {
assert(is Target target = resolveValue(jsonValue, targetType));
return target;
}

2) I have implemented special Iterable this way:
class JsonArrayIterable<Element>(JsonArray jsonValue, Type<Element> itemType) satisfies Iterable<Element> {
shared actual Iterator<Element> iterator() => object satisfies Iterator<Element> {
Iterator<Value> jsonIterator = jsonValue.iterator();
shared actual Element|Finished next() {
switch (next = jsonIterator.next())
case (is Value) {
return resolveValueTyped<Element>(next, itemType);
}
case (is Finished) {
return next;
}
}
};
}

3) Next I plan to use metamodel like this to instantiate this Iterable (and use it sequence() method for obtain desired result (this work is in progress right now):

value listType = `class JsonArrayIterable`.classApply<>(itemType);
.....

---
Oleg Neklyudov



четверг, 27 октября 2016 г., 13:12:56 UTC+3 пользователь Tako Schotanus написал:


-Tako

To unsubscribe from this group and stop receiving emails from it, send an email to ceylon-users...@googlegroups.com.

Oleg Neklyudov

unread,
Oct 27, 2016, 6:03:06 PM10/27/16
to ceylon-users
I know about serialization api and alabama library. Alabama library is serialization library that poorly fit "existing JSON-based REST API" as it site states. And I build library exactly for use with existing JSON-based REST API.


четверг, 27 октября 2016 г., 9:57:24 UTC+3 пользователь Lisi написал:

Oleg Neklyudov

unread,
Oct 27, 2016, 6:06:55 PM10/27/16
to ceylon-users
But thank you for idea to look at alabama for its solutions dealing with JSON mapping!

пятница, 28 октября 2016 г., 1:03:06 UTC+3 пользователь Oleg Neklyudov написал:

Oleg Neklyudov

unread,
Oct 27, 2016, 7:33:57 PM10/27/16
to ceylon-users, ta...@codejive.org
So, I have implemented this case with aproach mention earlier: https://github.com/ceylonforge/jsonmapper/commit/cb40ffb3a273c35c0f8ae255027b1230f4c7ff2a

But I take thought about using ceylon (de)serialization for such complex cases as typed collections.

пятница, 28 октября 2016 г., 0:40:08 UTC+3 пользователь Oleg Neklyudov написал:

Lisi

unread,
Oct 28, 2016, 3:07:10 AM10/28/16
to ceylon-users
The same manner you are going to instantiate JsonArrayIterable you may instantiate ceylon.language::Array and fill it with values:

value instance = `new Array.ofSize`.invoke([`Integer`], 3, 0);
value setFunction = `function Array.set`.memberApply<Nothing, Anything, Nothing>(type(instance)).bind(instance);
setFunction.apply( 0, 100 );
setFunction.apply( 1, 200 );
setFunction.apply( 2, 300 );
value getFunction = `function Array.get`.memberApply<Nothing, Anything, Nothing>(type(instance)).bind(instance);
for ( i in 0..2 ) {
print( getFunction.apply( i ) );
}




четверг, 27 октября 2016 г., 3:48:25 UTC+4 пользователь Oleg Neklyudov написал:
Hello!

Oleg Neklyudov

unread,
Oct 28, 2016, 10:22:11 AM10/28/16
to ceylon-users
Lisi, with constructor Array.ofSize I think there is problem because I need Array<T> where T is arbitrary type known only at runtime and constructor "ofSize" required instance of T to fill this array - but in general it is unknown how to instantiate this "zero" T instance.

пятница, 28 октября 2016 г., 10:07:10 UTC+3 пользователь Lisi написал:

Lisi

unread,
Oct 28, 2016, 11:55:00 AM10/28/16
to ceylon-users
that's exactly the metamodel is doing: `new Array.ofSize`.invoke(`list of type known at runtime`, size, fillWith) - first argument is a list of generic parametrs which of them may be unknown before runtime.

for the fillWith value, there are at least three solutions:
1) instantiate first value in the sequence and use this
2) use ArrayList and add function 
3) use optional parameter and fill with null and when array is ready apply narrow method

Dirk Lattermann

unread,
Oct 28, 2016, 5:18:28 PM10/28/16
to ceylon...@googlegroups.com
Hello Oleg,

don't know if your question is answered for you now, but maybe you mean
something like I did in Conjurup to convert query parameters to input
arguments for a function.

Please see in typeConverters.ceylon the methods
getListTypeConverterDynamicallyNN and
getNullableListTypeConverterDynamically:

https://github.com/dlkw/conjurup/blob/master/source/de/dlkw/conjurup/core/typeConverters.ceylon#L155

and maybe your JSON processor can be used together with conjurup, too!

Dirk

Oleg Neklyudov

unread,
Oct 31, 2016, 9:31:03 AM10/31/16
to ceylon-users
Hello Dirk!

Thank you for your answer!
I have already sucessfully solved my problem (code already on github - you can see it), but I will see your code to check for ideas.

I think jsonmapper I working on will be usable with you REST server - I will see for opportunities.

By the way next thing I need after jsonmapper is the REST client library (async/non-blocking desirable) - I plan to build it after jsonmapper - but maybe somebody already building it right now?

Oleg

суббота, 29 октября 2016 г., 0:18:28 UTC+3 пользователь Dirk Lattermann написал:
Reply all
Reply to author
Forward
0 new messages