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

Nested maps and arrays supported? #131

Closed
cclogg opened this Issue Aug 13, 2014 · 4 comments

Comments

Projects
None yet
4 participants
@cclogg

cclogg commented Aug 13, 2014

Hey I'm just wondering if there is an easy way in the current library to unpack msg-packed bytes into complete Java objects (including traversing down a map or array and converting those). Ie with JSON you can have a dictionary inside a dictionary inside an array etc... the iOS msg-pack library supports this through recursion. So far, using the available docs, the furthest I've gotten is having to manually parse each level of the nested msg-pack data into relevant Java objects.

Any help is appreciated, thanks!

@poros

This comment has been minimized.

Show comment
Hide comment
@poros

poros Sep 16, 2014

I would be interested in such a feature, too. msgpack-python already implements this behavior (it's simpler to achieve in Python, though). In order to be easily interchangeable with JSONObject, which also implements such a feature through the get() function, msgpack-java should expose a similar interface (maybe returning Value instead of Object)

poros commented Sep 16, 2014

I would be interested in such a feature, too. msgpack-python already implements this behavior (it's simpler to achieve in Python, though). In order to be easily interchangeable with JSONObject, which also implements such a feature through the get() function, msgpack-java should expose a similar interface (maybe returning Value instead of Object)

@seveniu

This comment has been minimized.

Show comment
Hide comment
@seveniu

seveniu Sep 17, 2014

i implements map , you can implements arrays like map, hope it might be of some help to you.

public class MapTemplate<K,V> extends AbstractTemplate<Map<K,V>> {
    private Class<K> kClass;
    private Class<V> vClass;
    private Template<K> keyTemplate;
    private Template<V> valueTemplate;


    @SuppressWarnings("unchecked")
    public MapTemplate() {
        Type type = getClass().getGenericSuperclass();
        Type[] trueType = ((ParameterizedType) type).getActualTypeArguments();
        this.kClass = (Class<K>) trueType[0];
        this.vClass = (Class<V>) trueType[1];
        keyTemplate= new AbstractTemplate<K>() {
            @Override
            public void write(Packer pk, K v, boolean required) throws IOException {
                pk.write(v);
            }

            @Override
            public K read(Unpacker u, K to, boolean required) throws IOException {
                return u.read(kClass);
            }
        };
        valueTemplate= new AbstractTemplate<V>() {
            @Override
            public void write(Packer pV, V v, boolean required) throws IOException {
                pV.write(v);
            }

            @Override
            public V read(Unpacker u, V to, boolean required) throws IOException {
                return u.read(vClass);
            }
        };
    }

    public void write(Packer pk, Map<K, V> target, boolean required)
            throws IOException {
        if (!(target instanceof Map)) {
            if (target == null) {
                if (required) {
                    throw new MessageTypeException("Attempted to write null");
                }
                pk.writeNil();
                return;
            }
            throw new MessageTypeException("Target is not a Map but " + target.getClass());
        }
        pk.writeMapBegin(target.size());
        for (Map.Entry<K, V> pair : target.entrySet()) {
            keyTemplate.write(pk, pair.getKey());
            valueTemplate.write(pk, pair.getValue());
        }
        pk.writeMapEnd();
    }

    public Map<K, V> read(Unpacker u, Map<K, V> to, boolean required)
            throws IOException {
        if (!required && u.trySkipNil()) {
            return null;
        }
        int n = u.readMapBegin();
        Map<K, V> map;
        if (to != null) {
            map = to;
            map.clear();
        } else {
            map = new HashMap<>(n);
        }
        for (int i = 0; i < n; i++) {
            K key = keyTemplate.read(u, null);
            V value = valueTemplate.read(u, null);
            map.put(key, value);
        }
        u.readMapEnd();
        return map;
    }
}

seveniu commented Sep 17, 2014

i implements map , you can implements arrays like map, hope it might be of some help to you.

public class MapTemplate<K,V> extends AbstractTemplate<Map<K,V>> {
    private Class<K> kClass;
    private Class<V> vClass;
    private Template<K> keyTemplate;
    private Template<V> valueTemplate;


    @SuppressWarnings("unchecked")
    public MapTemplate() {
        Type type = getClass().getGenericSuperclass();
        Type[] trueType = ((ParameterizedType) type).getActualTypeArguments();
        this.kClass = (Class<K>) trueType[0];
        this.vClass = (Class<V>) trueType[1];
        keyTemplate= new AbstractTemplate<K>() {
            @Override
            public void write(Packer pk, K v, boolean required) throws IOException {
                pk.write(v);
            }

            @Override
            public K read(Unpacker u, K to, boolean required) throws IOException {
                return u.read(kClass);
            }
        };
        valueTemplate= new AbstractTemplate<V>() {
            @Override
            public void write(Packer pV, V v, boolean required) throws IOException {
                pV.write(v);
            }

            @Override
            public V read(Unpacker u, V to, boolean required) throws IOException {
                return u.read(vClass);
            }
        };
    }

    public void write(Packer pk, Map<K, V> target, boolean required)
            throws IOException {
        if (!(target instanceof Map)) {
            if (target == null) {
                if (required) {
                    throw new MessageTypeException("Attempted to write null");
                }
                pk.writeNil();
                return;
            }
            throw new MessageTypeException("Target is not a Map but " + target.getClass());
        }
        pk.writeMapBegin(target.size());
        for (Map.Entry<K, V> pair : target.entrySet()) {
            keyTemplate.write(pk, pair.getKey());
            valueTemplate.write(pk, pair.getValue());
        }
        pk.writeMapEnd();
    }

    public Map<K, V> read(Unpacker u, Map<K, V> to, boolean required)
            throws IOException {
        if (!required && u.trySkipNil()) {
            return null;
        }
        int n = u.readMapBegin();
        Map<K, V> map;
        if (to != null) {
            map = to;
            map.clear();
        } else {
            map = new HashMap<>(n);
        }
        for (int i = 0; i < n; i++) {
            K key = keyTemplate.read(u, null);
            V value = valueTemplate.read(u, null);
            map.put(key, value);
        }
        u.readMapEnd();
        return map;
    }
}
@komamitsu

This comment has been minimized.

Show comment
Hide comment
@komamitsu

komamitsu Sep 29, 2014

Member

Sorry for my late reply.

We are developing msgpack-java v0.7.x now. It's faster and simpler than the older versions.
I integrated it and https://github.com/FasterXML/jackson-databind/ with https://github.com/komamitsu/jackson-dataformat-msgpack.

With the library, you can serialize nested array and map objects like this:

        Map<String, Object> map = new HashMap<>();
        map.put("str", "String");
        map.put("int", 1234);
        Map<String, String> childMap = new HashMap<>();
        childMap.put("abc", "ABC");
        childMap.put("xyz", "XYZ");
        map.put("childMap", childMap);
        List<Integer> childArray = new ArrayList<>();
        childArray.add(0);
        childArray.add(1);
        childArray.add(42);
        map.put("childArray", childArray);

        ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory());
        byte[] bytes = objectMapper.writeValueAsBytes(map);
        Object obj = objectMapper.readValue(bytes, new TypeReference<Map<String, Object>>() {});
        System.out.println(obj.toString());
        // ==> {str=String, childArray=[0, 1, 42], childMap={abc=ABC, xyz=XYZ}, int=1234}

If you're interested in it, please try it!

Member

komamitsu commented Sep 29, 2014

Sorry for my late reply.

We are developing msgpack-java v0.7.x now. It's faster and simpler than the older versions.
I integrated it and https://github.com/FasterXML/jackson-databind/ with https://github.com/komamitsu/jackson-dataformat-msgpack.

With the library, you can serialize nested array and map objects like this:

        Map<String, Object> map = new HashMap<>();
        map.put("str", "String");
        map.put("int", 1234);
        Map<String, String> childMap = new HashMap<>();
        childMap.put("abc", "ABC");
        childMap.put("xyz", "XYZ");
        map.put("childMap", childMap);
        List<Integer> childArray = new ArrayList<>();
        childArray.add(0);
        childArray.add(1);
        childArray.add(42);
        map.put("childArray", childArray);

        ObjectMapper objectMapper = new ObjectMapper(new MessagePackFactory());
        byte[] bytes = objectMapper.writeValueAsBytes(map);
        Object obj = objectMapper.readValue(bytes, new TypeReference<Map<String, Object>>() {});
        System.out.println(obj.toString());
        // ==> {str=String, childArray=[0, 1, 42], childMap={abc=ABC, xyz=XYZ}, int=1234}

If you're interested in it, please try it!

@poros

This comment has been minimized.

Show comment
Hide comment
@poros

poros Sep 30, 2014

Thanks to both of you.
@komamitsu I'll have a try, thanks!

poros commented Sep 30, 2014

Thanks to both of you.
@komamitsu I'll have a try, thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment