Re: Unable to properly tally all keys in nested json

Paul King <[email protected]>
Newsgroups gmane.comp.lang.groovy.user
Message-ID <CAMbkE7R-3NpA-grp7O_Zg-QcHRT57vf1HO5DFTD9paQXcGHOzg@mail.gmail.com>
I am not 100% sure what you are trying to capture in topValuesMap but for
tallyMap you probably want something like:

def tallyMap = [:].withDefault{ 0 }
def tally
tally = { Map json, String prefix ->
    json.each { k, v ->
        if (v instanceof List) {
          tallyMap[prefix + k] += 1
          v.each{ tally(it, "$prefix${k}.") }
        } else if (v?.toString().trim()) {
            tallyMap[prefix + k] += 1
            if (v instanceof Map) tally(v, "$prefix${k}.")
        }
    }
}

def root = new JsonSlurper().parse(inputStream)
def initialPrefix = ''
tally(root, initialPrefix)
println tallyMap

Output:
[name:1, age:1, address:1, address.street:1, address.city:1,
address.state:1, address.zip:1, phoneNumbers:1, phoneNumbers.type:2,
phoneNumbers.number:2]


<https://www.avast.com/sig-email?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail>
Virus-free.www.avast.com
<https://www.avast.com/sig-email?utm_medium=email&utm_source=link&utm_campaign=sig-email&utm_content=webmail>
<#DAB4FAD8-2DD7-40BB-A1B8-4E2AA1F9FDF2>

On Fri, May 12, 2023 at 10:38 AM James McMahon <[email protected]> wrote:

> I have this incoming json: { "name": "John Doe", "age": 42, "address": {
> "street": "123 Main St", "city": "Anytown", "state": "CA", "zip": "12345"
> }, "phoneNumbers": [ { "type": "home", "number": "555-1234" }, { "type":
> "work", "number": "555-5678" } ] } I wish to tally all the keys in this
> json in a map that gives me the key name as its key, and a count of the
> number of times the key occurs in the json as its value. For this example,
> the keys I expect in my output should include name, age, address,
> address.street, address.city, address.state, address.zip, phoneNumbers,
> phoneNumbers.type, and phoneNumbers.number. But I do not get that. Instead,
> I get this for the list of fields: triage.json.fields
> name,age,address,phoneNumbers And I get this for my tally count by key:
> triage.json.tallyMap [name:1, age:1, address:1, phoneNumbers:1]
>
> I am close, but not quite there. I don't capture all the keys. Here is my
> code. How must I modify this to get the result I require? import
> groovy.json.JsonSlurper import org.apache.commons.io.IOUtils import
> java.nio.charset.StandardCharsets def keys = [] def tallyMap = [:] def
> topValuesMap = [:] def ff = session.get() if (!ff) return try {
> session.read(ff, { inputStream -> def json = new
> JsonSlurper().parseText(IOUtils.toString(inputStream,
> StandardCharsets.UTF_8)) json.each { k, v -> if (v != null &&
> !v.toString().trim().isEmpty()) { tallyMap[k] = tallyMap.containsKey(k) ?
> tallyMap[k] + 1 : 1 if (topValuesMap.containsKey(k)) { def valuesMap =
> topValuesMap[k] valuesMap[v] = valuesMap.containsKey(v) ? valuesMap[v] + 1
> : 1 topValuesMap[k] = valuesMap } else { topValuesMap[k] = [:].withDefault{
> 0 }.plus([v: 1]) } } } } as InputStreamCallback) keys =
> tallyMap.keySet().toList() def tallyMapString = tallyMap.collectEntries {
> k, v -> [(k): v] }.toString() def topValuesMapString =
> topValuesMap.collectEntries { k, v -> [(k): v.sort{ -it.value }.take(10)]
> }.toString() ff = session.putAttribute(ff, 'triage.json.fields',
> keys.join(",")) ff = session.putAttribute(ff, 'triage.json.tallyMap',
> tallyMapString) ff = session.putAttribute(ff, 'triage.json.topValuesMap',
> topValuesMapString) session.transfer(ff, REL_SUCCESS) } catch (Exception e)
> { log.error('Error processing json fields', e) session.transfer(ff,
> REL_FAILURE) }
>
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.