Converts the *metadata* dictionary of a container or field into a
    ``flare.json`` formatted string or formatted stream written to the *file*

    The ``flare.json`` format is defined by the `d3.js <https://d3js.org/>`_ graphic
    library.

    The ``flare.json`` format looks like this:

    .. code-block:: JSON

        {
            "class": "class of the field or container",
            "name":  "name of the field or container",
            "size":  "bit size of the field",
            "value": "value of the field",
            "children": []
        }

    :param dict metadata: metadata generated from a :class:`Structure`,
        :class:`Sequence`, :class:`Array` or any :class:`Field` instance.
    :param file file: file-like object.

def d3flare_json(metadata, file=None, **options):
    """ Converts the *metadata* dictionary of a container or field into a
    ``flare.json`` formatted string or formatted stream written to the *file*

    The ``flare.json`` format is defined by the `d3.js <https://d3js.org/>`_ graphic
    library.

    The ``flare.json`` format looks like this:

    .. code-block:: JSON

        {
            "class": "class of the field or container",
            "name":  "name of the field or container",
            "size":  "bit size of the field",
            "value": "value of the field",
            "children": []
        }

    :param dict metadata: metadata generated from a :class:`Structure`,
        :class:`Sequence`, :class:`Array` or any :class:`Field` instance.
    :param file file: file-like object.
    """

    def convert(root):
        dct = OrderedDict()
        item_type = root.get('type')
        dct['class'] = root.get('class')
        dct['name'] = root.get('name')

        if item_type is ItemClass.Field.name:
            dct['size'] = root.get('size')
            dct['value'] = root.get('value')

        children = root.get('member')
        if children:
            # Any containable class with children
            dct['children'] = list()
            if item_type is ItemClass.Pointer.name:
                # Create pointer address field as child
                field = OrderedDict()
                field['class'] = dct['class']
                field['name'] = '*' + dct['name']
                field['size'] = root.get('size')
                field['value'] = root.get('value')
                dct['children'].append(field)
            for child in map(convert, children):
                # Recursive function call map(fnc, args).
                dct['children'].append(child)
        elif item_type is ItemClass.Pointer.name:
            # Null pointer (None pointer)
            dct['size'] = root.get('size')
            dct['value'] = root.get('value')
        return dct

    options['indent'] = options.get('indent', 2)

    if file:
        return json.dump(convert(metadata), file, **options)
    else:
        return json.dumps(convert(metadata), **options)