Подтвердить что ты не робот

Есть ли библиотека для десериализации с помощью python, которая сериализована с помощью java

Есть ли библиотека для десериализации с помощью python, которая сериализована с помощью java?

4b9b3361

Ответ 1

Сериализация Java представляет собой представление структуры класса/данных и тесно связана с виртуальной машиной. Следовательно, трудно будет перевести мир Python.

  • Ваша Java-программа может сериализовать/десериализоваться в XML, которая будет переводимой. Проверьте JAXB или XStream
  • Вы рассмотрели возможность работы в Jython - реализация Python в Java

Ответ 2

Здесь очень, очень грубая реализация, которая не требует импорта. Трудность здесь состоит в том, что некоторые классы имеют пользовательские сериализаторы, которые требуют, чтобы исходный код десериализовался. Кроме того, мой файл был gzip'd, хотя для этого я не использовал код. Я использовал эти две страницы для справки:

http://www.javaworld.com/community/node/2915 http://docs.oracle.com/javase/7/docs/platform/serialization/spec/protocol.html

#!/usr/bin/python

def parse(f):
    h = lambda s: ' '.join('%.2X' % ord(x) for x in s) # format as hex
    p = lambda s: sum(ord(x)*256**i for i, x in enumerate(reversed(s))) # parse integer
    magic = f.read(2)
    assert magic == '\xAC\xED', h(magic) # STREAM_MAGIC
    assert p(f.read(2)) == 5 # STREAM_VERSION
    handles = []
    def parse_obj():
        b = f.read(1)
        if not b:
            raise StopIteration # not necessarily the best thing to throw here.
        if b == '\x70': # p TC_NULL
            return None
        elif b == '\x71': # q TC_REFERENCE
            handle = p(f.read(4)) - 0x7E0000 # baseWireHandle
            o = handles[handle]
            return o[1]
        elif b == '\x74': # t TC_STRING
            string = f.read(p(f.read(2))).decode('utf-8')
            handles.append(('TC_STRING', string))
            return string
        elif b == '\x75': # u TC_ARRAY
            data = []
            cls = parse_obj()
            size = p(f.read(4))
            handles.append(('TC_ARRAY', data))
            assert cls['_name'] in ('[B', '[I'), (cls['_name'], size, f.read(50))
            for x in range(size):
                data.append(f.read({'[B': 1, '[I': 4}[cls['_name']]))
            return data
        elif b == '\x7E': # ~ TC_ENUM
            enum = {}
            enum['_cls'] = parse_obj()
            handles.append(('TC_ENUM', enum))
            enum['_name'] = parse_obj()
            return enum
        elif b == '\x72': # r TC_CLASSDESC
            cls = {'fields': []}
            full_name = f.read(p(f.read(2)))
            cls['_name'] = full_name.split('.')[-1] # i don't care about full path
            f.read(8) # uid
            cls['flags'] = f.read(1)
            handles.append(('TC_CLASSDESC', cls))
            assert cls['flags'] in ('\2', '\3', '\x0C', '\x12'), h(cls['flags'])
            b = f.read(2)
            for i in range(p(b)):
                typ = f.read(1)
                name = f.read(p(f.read(2)))
                fcls = parse_obj() if typ in 'L[' else ''
                cls['fields'].append((name, typ, fcls.split('/')[-1])) # don't care about full path
            b = f.read(1)
            assert b == '\x78', h(b)
            cls['parent'] = parse_obj()
            return cls
        # TC_OBJECT
        assert b == '\x73', (h(b), h(f.read(4)), f.read(50))
        obj = {}
        obj['_cls'] = parse_obj()
        obj['_name'] = obj['_cls']['_name']
        handle = len(handles)
        parents = [obj['_cls']]
        while parents[0]['parent']:
            parents.insert(0, parents[0]['parent'])
        handles.append(('TC_OBJECT', obj))
        for cls in parents:
            for name, typ, fcls in cls['fields'] if cls['flags'] in ('\2', '\3') else []:
                if typ == 'I': # Integer
                    obj[name] = p(f.read(4))
                elif typ == 'S': # Short
                    obj[name] = p(f.read(2))
                elif typ == 'J': # Long
                    obj[name] = p(f.read(8))
                elif typ == 'Z': # Bool
                    b = f.read(1)
                    assert p(b) in (0, 1)
                    obj[name] = bool(p(b))
                elif typ == 'F': # Float
                    obj[name] = h(f.read(4))
                elif typ in 'BC': # Byte, Char
                    obj[name] = f.read(1)
                elif typ in 'L[': # Object, Array
                    obj[name] = parse_obj()
                else: # Unknown
                    assert False, (name, typ, fcls)
            if cls['flags'] in ('\3', '\x0C'): # SC_WRITE_METHOD, SC_BLOCKDATA
                b = f.read(1)
                if b == '\x77': # see the readObject / writeObject methods
                    block = f.read(p(f.read(1)))
                    if cls['_name'].endswith('HashMap') or cls['_name'].endswith('Hashtable'):
                        # http://javasourcecode.org/html/open-source/jdk/jdk-6u23/java/util/HashMap.java.html
                        # http://javasourcecode.org/html/open-source/jdk/jdk-6u23/java/util/Hashtable.java.html
                        assert len(block) == 8, h(block)
                        size = p(block[4:])
                        obj['data'] = [] # python doesn't allow dicts as keys
                        for i in range(size):
                            k = parse_obj()
                            v = parse_obj()
                            obj['data'].append((k, v))
                        try:
                            obj['data'] = dict(obj['data'])
                        except TypeError:
                            pass # non hashable keys
                    elif cls['_name'].endswith('HashSet'):
                        # http://javasourcecode.org/html/open-source/jdk/jdk-6u23/java/util/HashSet.java.html
                        assert len(block) == 12, h(block)
                        size = p(block[-4:])
                        obj['data'] = []
                        for i in range(size):
                            obj['data'].append(parse_obj())
                    elif cls['_name'].endswith('ArrayList'):
                        # http://javasourcecode.org/html/open-source/jdk/jdk-6u23/java/util/ArrayList.java.html
                        assert len(block) == 4, h(block)
                        obj['data'] = []
                        for i in range(obj['size']):
                            obj['data'].append(parse_obj())
                    else:
                        assert False, cls['_name']
                    b = f.read(1)
                assert b == '\x78', h(b) + ' ' + repr(f.read(50)) # TC_ENDBLOCKDATA
        handles[handle] = ('py', obj)
        return obj
    objs = []
    while 1:
        try:
            objs.append(parse_obj())
        except StopIteration:
            return objs

if __name__ == '__main__':
    import sys, json
    json.dump(parse(sys.stdin), sys.stdout, indent=2)

Ответ 3

Java-двоичная сериализация действительно предназначена для использования с Java. Чтобы сделать это на Python, вам нужно будет иметь все соответствующие классы Java для проверки и создать объекты Python соответствующим образом - это было бы довольно отвратительно и хрупко.

Вам лучше использовать кросс-платформенный формат сериализации, такой как Thrift, Protocol Buffers, JSON или XML. Если вы не можете изменить, какой формат сериализации используется в Java-коде, я бы предложил написать новый Java-код, который десериализуется из двоичного формата и затем ресериализуется в кросс-платформенном формате.

Ответ 4

Вы не говорите, имеете ли вы контроль над сериализацией данных или нет, но если вы это сделаете, JSON кажется чтобы быть хорошим форматом, который является кросс-платформенным и имеет хороший баланс между читаемым человеком и машиночитаемым. Для java и распространяемый с помощью python.

Ответ 5

Если бы я был вами, я бы прочитал данные с Jython и либо перезариентировал его с помощью pickle (так что вы можете прочитать его с Python) или в формате нейтрального языка, например XML.

Ответ 6

Если вы используете Java-классы, то я даже не знаю, что бы это означало для десериализации класса Java в среде Python. Если вы используете простые примитивы (ints, float, strings), то, вероятно, было бы не слишком сложно создать библиотеку Python, которая могла бы десериализовать формат Java.

Но, как говорили другие, есть лучшие кросс-платформенные решения.

Ответ 7

Другой вариант - использовать Перспективный брокер из Twisted. Их реализация Java. Если вам просто нужна сериализация/десериализация, вы можете использовать только Banana (протокол) или Jelly (постоянство). Желе - это сохранение объектов на основе S-выражений.