1

Currently im trying to transform this python dict to a html unordered list:

{'dataStreamId': 'raw:com.google.nutrition:NutritionSource', 'dataStreamName': 'NutritionSource', 'type': 'raw', 'dataType': {'name': 'com.google.nutrition', 'field': [{'name': 'nutrients', 'format': 'map'}, {'name': 'meal_type', 'format': 'integer', 'optional': True}, {'name': 'food_item', 'format': 'string', 'optional': True}]}, 'application': {'version': '1', 'detailsUrl': 'http://example.com', 'name': 'My Example App'}, 'dataQualityStandard': []}

with this function:

def dict_to_html_ul(dd, level=4):
    import simplejson
    text = '<ul>'
    for k, v in dd.items():
        text += '<li><b>%s</b>: %s</li>' % (k, dict_to_html_ul(v, level+1) if isinstance(v, (dict)) else (simplejson.dumps(v) if isinstance(v, list) else v))
    text += '</ul>'
    return text

but I am getting this result:

<ul>
    <li><b>dataStreamId</b>: raw:com.google.nutrition:NutritionSource</li>
    <li><b>dataStreamName</b>: NutritionSource</li>
    <li><b>type</b>: raw</li>
    <li><b>dataType</b>: <ul>
            <li><b>name</b>: com.google.nutrition</li>
            <li><b>field</b>: [{"name": "nutrients", "format": "map"}, {"name": "meal_type", "format": "integer",
                "optional": true}, {"name": "food_item", "format": "string", "optional": true}]</li>
        </ul>
    </li>
    <li><b>application</b>: <ul>
            <li><b>version</b>: 1</li>
            <li><b>detailsUrl</b>: http://example.com</li>
            <li><b>name</b>: My Example App</li>
        </ul>
    </li>
    <li><b>dataQualityStandard</b>: []</li>
</ul>

And I am having issues trying to fix the result, basically I wanted to transform the rest of the result in the same way as the function was going.

I tried to transform the text with some string replacing after the function:

text = text.replace('[','').replace(']', '')
text= text.replace('{', '<br>' + '&nbsp;' * level).replace('}', '')
text = text.replace(',', '<br>' + '&nbsp;' * (level-1))

It came out with some extraspacing and I could not replace some parts like this:

"word": "word"

So I tried to make a "re.sub()" but did not have success.

Edit:

Expected output:

<ul>
    <li><b>dataStreamId</b>: raw:com.google.nutrition:NutritionSource</li>
    <li><b>dataStreamName</b>: NutritionSource</li>
    <li><b>type</b>: raw</li>
    <li><b>dataType</b>:
        <ul>
            <li><b>name</b>: com.google.nutrition</li>
            <li><b>field</b>:
                <ul>
                    <li><b>name</b>: nutrients</li>
                    <li><b>format</b>: map</li>
                    <br>
                    <li><b>name</b>: meal_type</li>
                    <li><b>format</b>: integer</li>
                    <li><b>optional</b>: true</li>
                    <br>
                    <li><b>name</b>: food_item</li>
                    <li><b>format</b>: string</li>
                    <li><b>optional</b>: true</li>
                </ul>
            </li>
        </ul>
    </li>
    <li><b>application</b>: <ul>
            <li><b>version</b>: 1</li>
            <li><b>detailsUrl</b>: http://example.com</li>
            <li><b>name</b>: My Example App</li>
        </ul>
    </li>
    <li><b>dataQualityStandard</b>: []</li>
</ul>

Edit2: Thanks for the answer @AndrejKesely

I actually got the proper html in the first specific dict, but I have another dict that didnt actually work with this function: –

a = {'minStartTimeNs': '1573159699023000000', 'maxEndTimeNs': '1573159699023999000', 'dataSourceId': 'raw:com.google.nutrition:NutritionSource', 'point': [{'startTimeNanos': '1573159699023000000', 'endTimeNanos': '1573159699023999000', 'dataTypeName': 'com.google.nutrition', 'value': [{'mapVal': [{'key': 'fat.total', 'value': {'fpVal': 0.4}}, {'key': 'sodium', 'value': {'fpVal': 1}}, {'key': 'fat.saturated', 'value': {
'fpVal': 0.1}}, {'key': 'protein', 'value': {'fpVal': 1.3}}, {'key': 'carbs.total', 'value': {'fpVal': 27}}, {'key': 'cholesterol', 'value': {'fpVal': 0}}, {'key': 'calories', 'value': {'fpVal': 105}}, {'key': 'sugar', 'value': {'fpVal': 14}}, {'key': 'dietary_fiber', 'value': {'fpVal': 3.1}}, {'key': 'potassium', 'value': {'fpVal': 422}}]}, {'intVal': 4, 'mapVal': []}, {'stringVal': 'apple', 'mapVal': []}]}]}

I was expecting a function that could work for both

but the output with get_html() in the other dict outputs:

<ul>
    <li><b>minStartTimeNs</b>: 1573159699023000000</li>
    <li><b>maxEndTimeNs</b>: 1573159699023999000</li>
    <li><b>dataSourceId</b>: raw:com.google.nutrition:NutritionSource</li>
    <li><b>point</b>: <ul>
            <li><b>startTimeNanos</b>: 1573159699023000000</li>
            <li><b>endTimeNanos</b>: 1573159699023999000</li>
            <li><b>dataTypeName</b>: com.google.nutrition</li>
            <li><b>value</b>: [{'mapVal': [{'key': 'fat.total', 'value': {'fpVal': 0.4}}, {'key': 'sodium', 'value':
                {'fpVal': 1}}, {'key': 'fat.saturated', 'value': {'fpVal': 0.1}}, {'key': 'protein', 'value': {'fpVal':
                1.3}}, {'key': 'carbs.total', 'value': {'fpVal': 27}}, {'key': 'cholesterol', 'value': {'fpVal': 0}},
                {'key': 'calories', 'value': {'fpVal': 105}}, {'key': 'sugar', 'value': {'fpVal': 14}}, {'key':
                'dietary_fiber', 'value': {'fpVal': 3.1}}, {'key': 'potassium', 'value': {'fpVal': 422}}]}, {'intVal':
                4, 'mapVal': []}, {'stringVal': 'apple', 'mapVal': []}]</li>
        </ul>
    </li>
</ul>

And I was expecting:

<ul>
    <li><b>minStartTimeNs</b>: 1573159699023000000</li>
    <li><b>maxEndTimeNs</b>: 1573159699023999000</li>
    <li><b>dataSourceId</b>: raw:com.google.nutrition:NutritionSource</li>
    <li><b>point</b>: <ul>
            <li><b>startTimeNanos</b>: 1573159699023000000</li>
            <li><b>endTimeNanos</b>: 1573159699023999000</li>
            <li><b>dataTypeName</b>: com.google.nutrition</li>
            <li><b>value</b>:
                <ul>
                    <li><b>mapVal</b>:
                    <ul>
                        <li><b>key</b>: fat.total</li>
                        <li><b>value</b>:
                            <ul>
                                <li><b>fpVal</b>: 0.4</li>
                            </ul>
                        </li>
                        <br>
                        <li><b>key</b>: sodium</li>
                        <li><b>value</b>:
                            <ul>
                                <li><b>fpVal</b>: 1</li>
                            </ul>
                        </li>
                        <br>
                        <li><b>key</b>:</li> 'fat.saturated',
                        <li><b>value</b>:
                            <ul>
                                <li><b>fpVal</b>: 0.4</li>
                            </ul>
                        </li>
                        <br>
                        <li><b>key</b>:</li> 'protein',
                        <li><b>value</b>:
                            <ul>
                                <li><b>fpVal</b>: 5.4</li>
                            </ul>
                        </li>
                        <br>
                        <li><b>key</b>:</li> 'carbs.total',
                        <li><b>value</b>:
                            <ul>
                                <li><b>fpVal</b>: 6.4</li>
                            </ul>
                        </li>
                        <br>
                        <li><b>key</b>:</li> 'cholesterol',
                        <li><b>value</b>:
                            <ul>
                                <li><b>fpVal</b>: 4.5</li>
                            </ul>
                        </li>
                        <br>
                        <li><b>key</b>:</li> 'calories',
                        <li><b>value</b>:
                            <ul>
                                <li><b>fpVal</b>: 3.4</li>
                            </ul>
                        </li>
                        <br>
                        <li><b>key</b>:</li> 'sugar',
                        <li><b>value</b>:
                            <ul>
                                <li><b>fpVal</b>: 5.5</li>
                            </ul>
                        </li>
                        <br>
                        <li><b>key</b>:</li>'dietary_fiber',
                        <li><b>value</b>:
                            <ul>
                                <li><b>fpVal</b>: 1</li>
                            </ul>
                        </li>
                        <br>
                        <li><b>key</b>:</li> 'potassium',
                        <li><b>value</b>:
                            <ul>
                                <li><b>fpVal</b>: 2</li>
                            </ul>
                        </li>
                        <br>
                    </ul>
                    <li><b>intVal</b>: 4</li>
                    <li><b>mapVal</b>: []</li>
                    <br>
                    <li><b>stringVal</b>: apple</li>
                    <li><b>mapVal</b>: []</li>
                </li>
                </ul>
            </li>
        </ul>
    </li>
</ul>
2
  • Can you please edit your question and put there expeceted result (html)? Commented Nov 30, 2022 at 13:57
  • Hey @AndrejKesely, I added the expected result and properly showed the current result (string) I am getting. Commented Nov 30, 2022 at 14:15

2 Answers 2

1

Try:

dct = {
    "dataStreamId": "raw:com.google.nutrition:NutritionSource",
    "dataStreamName": "NutritionSource",
    "type": "raw",
    "dataType": {
        "name": "com.google.nutrition",
        "field": [
            {"name": "nutrients", "format": "map"},
            {"name": "meal_type", "format": "integer", "optional": True},
            {"name": "food_item", "format": "string", "optional": True},
        ],
    },
    "application": {
        "version": "1",
        "detailsUrl": "http://example.com",
        "name": "My Example App",
    },
    "dataQualityStandard": [],
}


def get_html(o):
    s = ""

    if isinstance(o, dict):
        s += "<ul>\n"

        for k, v in o.items():
            s += f"<li><b>{k}</b>: " + get_html(v) + "</li>\n"

        s += "</ul>"
    elif isinstance(o, list):
        s += "<ul>\n"

        if not o:
            return str(o)
        else:
            out = []
            for v in o:
                ss = ""
                for kk, vv in v.items():
                    ss += f"<li><b>{kk}</b>: {vv}</li>\n"
                out.append(ss)

            s += "<br>\n".join(out)
            s += "</ul>"
    else:
        return str(o)

    return s


print(get_html(dct))

Prints ("beautified" result):

<ul>
    <li><b>dataStreamId</b>: raw:com.google.nutrition:NutritionSource</li>
    <li><b>dataStreamName</b>: NutritionSource</li>
    <li><b>type</b>: raw</li>
    <li><b>dataType</b>:
        <ul>
            <li><b>name</b>: com.google.nutrition</li>
            <li><b>field</b>:
                <ul>
                    <li><b>name</b>: nutrients</li>
                    <li><b>format</b>: map</li>
                    <br>
                    <li><b>name</b>: meal_type</li>
                    <li><b>format</b>: integer</li>
                    <li><b>optional</b>: True</li>
                    <br>
                    <li><b>name</b>: food_item</li>
                    <li><b>format</b>: string</li>
                    <li><b>optional</b>: True</li>
                </ul>
            </li>
        </ul>
    </li>
    <li><b>application</b>:
        <ul>
            <li><b>version</b>: 1</li>
            <li><b>detailsUrl</b>: http://example.com</li>
            <li><b>name</b>: My Example App</li>
        </ul>
    </li>
    <li><b>dataQualityStandard</b>: []</li>
</ul>
Sign up to request clarification or add additional context in comments.

1 Comment

Hello @AndrejKesely thank you for the answer. I edited my question, so you can see more information but: Your function get_html(), worked as intended on the first dict, but on the second one didnt have the output expected
1

Got this function to work thanks to @AndrejKesely for basically crushing it

def get_html(o):
    s = ""
    if isinstance(o, dict):
        s += "<ul>\n"
        for k, v in o.items():
            s += f"<li><b>{k}</b>: " + get_html(v) + "</li>\n"
        s += "</ul>"
    elif isinstance(o, list):
        s += "<ul>\n"
        if not o:
            return str(o)
        else:
            out = []
            for v in o:
                ss = ""
                for kk, vv in v.items():
                    ss += f"<li><b>{kk}</b>:" + get_html(vv) + " </li>\n"
                out.append(ss)
            s += "<br>\n".join(out)
            s += "</ul>"
    else:
        return str(o)
    return s

The only thing I changed in his function so it could work in any list/dict was make this:

            for v in o:
                ss = ""
                for kk, vv in v.items():
                    ss += f"<li><b>{kk}</b>: {vv}</li>\n"
                out.append(ss)

become iterative like this:

            for v in o:
                ss = ""
                for kk, vv in v.items():
                    ss += f"<li><b>{kk}</b>:" + get_html(vv) + " </li>\n"
                out.append(ss)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.