jsonbashjq

jq parse string array and string object


I have this json string:

json_string="{\"emailRecipients\":\"['test@example.com', 'tes2t@example.com', 'test3@example.com']\", \"anotherEmails\":\"{'test1': 'test1@example.com', 'test2': 'test2@example.com', 'test3': 'test3@example.com'}\", \"some_key\": 3, \"another_key\": \"some_value\"}"

I'm trying to use jq to parse the emailRecipients as a json array and anotherEmails as a json object.

I'm trying to make a command that can work with any key, not emailRecipients just and anotherEmails. I also need to keep keys-values that don't have json objects/arrays inside intact.

So I tried to do this:

parsed_json=$(echo "$json_string" | jq 'with_entries(
    .value |= if startswith("\"[") and endswith("\"]") then
        gsub("''";"\"") | fromjson
    else
        .
    end
)')

But I don't know why the gsub isn't working. Any idea of what I'm doing wrong ?


Solution

  • You seem to be confusing syntax with values. The quotes are not part of the value; the value starts and ends with [ and ], respectively (not "[ and "]; the latter doesn't even make sense if the syntax quote was part of the value). To detect objects, you need to check for { and } prefix and suffix. You need to filter for string values, otherwise you cannot apply the startswith filter.

    Note that your values are not valid JSON. However, if you still want to continue, here's the full program:

    map_values(
        if type == "string" and (startswith("[") and endswith("]") or startswith("{") and endswith("}")) then
            gsub("'"; "\"") | fromjson
        else
            .
        end
    )
    

    When used in a shell context:

    parsed_json=$(printf '%s\n' "$json_string" | jq 'map_values(
        if type == "string" and (startswith("[") and endswith("]") or startswith("{") and endswith("}")) then
            gsub("'\''"; "\"") | fromjson
        else
            .
        end
    )')
    

    or

    parsed_json=$(printf '%s\n' "$json_string" | jq "map_values(
        if type == \"string\" and (startswith(\"[\") and endswith(\"]\") or startswith(\"{\") and endswith(\"}\")) then
            gsub(\"'\"; \"\\\"\") | fromjson
        else
            .
        end
    )")