How to extract the path info? - json

For the following JSON, I'd like to extract something like this ( is a TAB character).
CHROMOSOMES<TAB>HUMAN<TAB>1<TAB>1
...
STATUSES<TAB>name<TAB>Approved
...
ATTRIBUTES<TAB>HGNC<TAB>HGNC ID<TAB>gd_hgnc_id
...
ATTRIBUTES<TAB>EXTERNAL<TAB>NCBI Gene ID<TAB>md_eg_id<TAB>NCBI
...
ORDER_BY<TAB>HGNC ID<TAB>gd_hgnc_id
...
I'd like a smart way to extract the path info of this tree structure. Could you anybody show me the best way to do so? Thanks.
{
"CHROMOSOMES": {
"HUMAN": [
{
"name": "1",
"value": "1"
},
{
"name": "2",
"value": "2"
},
{
"name": "3",
"value": "3"
},
{
"name": "4",
"value": "4"
},
{
"name": "5",
"value": "5"
},
{
"name": "6",
"value": "6"
},
{
"name": "7",
"value": "7"
},
{
"name": "8",
"value": "8"
},
{
"name": "9",
"value": "9"
},
{
"name": "10",
"value": "10"
},
{
"name": "11",
"value": "11"
},
{
"name": "12",
"value": "12"
},
{
"name": "13",
"value": "13"
},
{
"name": "14",
"value": "14"
},
{
"name": "15",
"value": "15"
},
{
"name": "16",
"value": "16"
},
{
"name": "17",
"value": "17"
},
{
"name": "18",
"value": "18"
},
{
"name": "19",
"value": "19"
},
{
"name": "20",
"value": "20"
},
{
"name": "21",
"value": "21"
},
{
"name": "22",
"value": "22"
},
{
"name": "X",
"value": "X"
},
{
"name": "Y",
"value": "Y"
},
{
"name": "reserved loci",
"value": "reserved"
},
{
"name": "mitochondrial",
"value": "mito"
},
{
"name": "pseudoautosomal",
"value": "XandY"
}
]
},
"STATUSES": [
{
"name": "Approved",
"value": "Approved"
},
{
"name": "Entry and symbol withdrawn",
"value": "Entry Withdrawn"
}
],
"ATTRIBUTES": {
"HGNC": [
{
"name": "HGNC ID",
"value": "gd_hgnc_id"
},
{
"name": "Approved symbol",
"value": "gd_app_sym"
},
{
"name": "Approved name",
"value": "gd_app_name"
},
{
"name": "Status",
"value": "gd_status"
},
{
"name": "Locus type",
"value": "gd_locus_type"
},
{
"name": "Locus group",
"value": "gd_locus_group"
},
{
"name": "Previous symbols",
"value": "gd_prev_sym"
},
{
"name": "Previous name",
"value": "gd_prev_name"
},
{
"name": "Synonyms",
"value": "gd_aliases"
},
{
"name": "Name synonyms",
"value": "gd_name_aliases"
},
{
"name": "Chromosome",
"value": "gd_pub_chrom_map"
},
{
"name": "Date approved",
"value": "gd_date2app_or_res"
},
{
"name": "Date modified",
"value": "gd_date_mod"
},
{
"name": "Date symbol changed",
"value": "gd_date_sym_change"
},
{
"name": "Date name changed",
"value": "gd_date_name_change"
},
{
"name": "Accession numbers",
"value": "gd_pub_acc_ids"
},
{
"name": "Enzyme IDs",
"value": "gd_enz_ids"
},
{
"name": "NCBI Gene ID",
"value": "gd_pub_eg_id"
},
{
"name": "Ensembl gene ID",
"value": "gd_pub_ensembl_id"
},
{
"name": "Mouse genome database ID",
"value": "gd_mgd_id"
},
{
"name": "Specialist database links",
"value": "gd_other_ids"
},
{
"name": "Specialist database IDs",
"value": "gd_other_ids_list"
},
{
"name": "Pubmed IDs",
"value": "gd_pubmed_ids"
},
{
"name": "RefSeq IDs",
"value": "gd_pub_refseq_ids"
},
{
"name": "Gene group ID",
"value": "family.id"
},
{
"name": "Gene group name",
"value": "family.name"
},
{
"name": "CCDS IDs",
"value": "gd_ccds_ids"
},
{
"name": "Vega IDs",
"value": "gd_vega_ids"
},
{
"name": "Locus specific databases",
"value": "gd_lsdb_links"
}
],
"EXTERNAL": [
{
"name": "NCBI Gene ID",
"source": "NCBI",
"value": "md_eg_id"
},
{
"name": "OMIM ID",
"source": "OMIM",
"value": "md_mim_id"
},
{
"name": "RefSeq",
"source": "NCBI",
"value": "md_refseq_id"
},
{
"name": "UniProt ID",
"source": "UniProt",
"value": "md_prot_id"
},
{
"name": "Ensembl ID",
"source": "Ensembl",
"value": "md_ensembl_id"
},
{
"name": "Vega ID",
"source": "Vega",
"value": "md_vega_id"
},
{
"name": "UCSC ID",
"source": "UCSC",
"value": "md_ucsc_id"
},
{
"name": "Mouse genome database ID",
"source": "MGI",
"value": "md_mgd_id"
},
{
"name": "Rat genome database ID",
"source": "RGD",
"value": "md_rgd_id"
},
{
"name": "LNCipedia",
"source": "LNCipedia",
"value": "md_lncipedia"
},
{
"name": "GtRNAdb",
"source": "GtRNAdb",
"value": "md_gtrnadb"
}
]
},
"ORDER_BY": [
{
"name": "HGNC ID",
"value": "gd_hgnc_id"
},
{
"name": "Approved symbol",
"value": "gd_app_sym_sort"
},
{
"name": "Approved name",
"value": "gd_app_name"
},
{
"name": "Status",
"value": "gd_status"
},
{
"name": "Locus type",
"value": "gd_locus_type"
},
{
"name": "Locus group",
"value": "gd_locus_group"
},
{
"name": "Previous symbols",
"value": "gd_prev_sym"
},
{
"name": "Previous name",
"value": "gd_prev_name"
},
{
"name": "Synonyms",
"value": "gd_aliases"
},
{
"name": "Name synonyms",
"value": "gd_name_aliases"
},
{
"name": "Chromosome",
"value": "gd_pub_chrom_map_sort"
},
{
"name": "Date approved",
"value": "gd_date2app_or_res"
},
{
"name": "Date modified",
"value": "gd_date_mod"
},
{
"name": "Date symbol changed",
"value": "gd_date_sym_change"
},
{
"name": "Date name changed",
"value": "gd_date_name_change"
},
{
"name": "Accession numbers",
"value": "gd_pub_acc_ids"
},
{
"name": "Enzyme IDs",
"value": "gd_enz_ids"
},
{
"name": "NCBI Gene ID",
"value": "gd_pub_eg_id"
},
{
"name": "Ensembl gene ID",
"value": "gd_pub_ensembl_id"
},
{
"name": "Mouse genome database ID",
"value": "gd_mgd_id"
},
{
"name": "Specialist database links",
"value": "gd_other_ids"
},
{
"name": "Specialist database IDs",
"value": "gd_other_ids_list"
},
{
"name": "Pubmed IDs",
"value": "gd_pubmed_ids"
},
{
"name": "RefSeq IDs",
"value": "gd_pub_refseq_ids"
},
{
"name": "Gene group ID",
"value": "family.id"
},
{
"name": "Gene group name",
"value": "family.name"
},
{
"name": "CCDS IDs",
"value": "gd_ccds_ids"
},
{
"name": "Vega IDs",
"value": "gd_vega_ids"
},
{
"name": "Locus specific databases",
"value": "gd_lsdb_links"
},
{
"name": "NCBI Gene ID (supplied by NCBI)",
"value": "md_eg_id"
},
{
"name": "OMIM ID (supplied by OMIM)",
"value": "md_mim_id"
},
{
"name": "RefSeq (supplied by NCBI)",
"value": "md_refseq_id"
},
{
"name": "UniProt ID (supplied by UniProt)",
"value": "md_prot_id"
},
{
"name": "Ensembl ID (supplied by Ensembl)",
"value": "md_ensembl_id"
},
{
"name": "Vega ID (supplied by Vega)",
"value": "md_vega_id"
},
{
"name": "UCSC ID (supplied by UCSC)",
"value": "md_ucsc_id"
},
{
"name": "Mouse genome database ID (supplied by MGI)",
"value": "md_mgd_id"
},
{
"name": "Rat genome database ID (supplied by RGD)",
"value": "md_rgd_id"
},
{
"name": "LNCipedia ID (supplied by LNCipedia)",
"value": "md_lncipedia"
},
{
"name": "GtRNAdb ID (supplied by GtRNAdb)",
"value": "md_gtrnadb"
}
],
"OUTPUT": [
"Text",
"Make URL for text"
]
}

I'd like a smart way to extract the path info of this tree structure.
paths is your friend.
Given certain irregularities in the input, the exact requirements are
not always clear, but the following might be what you are looking for
and even if not, it would be easy to tweak in accordance with your
detailed requirements.
totsv.jq
def s: map(select(type=="string"));
paths as $p
| getpath($p)
| if type == "object" and has("name")
then ($p|s) + [.name, .value, (.source // empty)]
elif type == "array" and .[0] == "Text" then ($p|s) + .
else empty
end
| #tsv
Invocation
jq -crf totsv.jq chromosomes.json
Selection from output
CHROMOSOMES HUMAN 1 1
CHROMOSOMES HUMAN 2 2
...
STATUSES Approved Approved
STATUSES Entry and symbol withdrawn Entry Withdrawn
ATTRIBUTES HGNC HGNC ID gd_hgnc_id
...
ORDER_BY GtRNAdb ID (supplied by GtRNAdb) md_gtrnadb
OUTPUT Text Make URL for text
For future reference
Rather than give a very long sample input, it would be better
to give a small sample that is tightly woven with detailed requirements.

Related

Dependent field in another dependent field

I have a form with dependent fields that works fine, but now I'm trying to add a second dependent field, that will rely on my first dependent field:
{
"job_level": {
"type": "select",
"label": "Job Level",
"order": 8,
"state": "required",
"selection_values": [
{
"id": "",
"label": "* Job Level"
},
{
"id": "c_level",
"label": "C-Level"
},
{
"id": "architect",
"label": "Architect"
}
]
},
"job_function": {
"type": "select",
"label": "Job Function",
"order": 9,
"state": "required",
"dependent_field": {
"name": "job_level",
"values": [
"c_level",
"architect"
]
},
"selection_values": {
"c_level": [
{
"id": "",
"label": "* Job Function"
},
{
"id": "Security",
"label": "Security"
},
{
"id": "HR",
"label": "HR"
}
],
"architect": [
{
"id": "",
"label": "* Job Function"
},
{
"id": "Sales",
"label": "Sales"
}
]
}
},
"job_role": {
"type": "select",
"label": "Job Role",
"order": 10,
"state": "required",
"dependent_field": {
"name": "job_function",
"values": [
"Security",
"HR",
"Sales"
]
},
"selection_values": {
"Security": [
{
"id": "",
"label": "* Job Role"
},
{
"id": "CISO",
"label": "CISO"
},
{
"id": "CSO",
"label": "CSO"
},
{
"id": "Other",
"label": "Other"
}
],
"HR": [
{
"id": "",
"label": "* Job Role"
},
{
"id": "CHRO",
"label": "CHRO"
},
{
"id": "Other",
"label": "Other"
}
],
"Sales": [
{
"id": "",
"label": "* Job Role"
},
{
"id": "Operations_Sales",
"label": "Operations/Sales"
},
{
"id": "Other",
"label": "Other"
}
]
}
}
}
job_role is the field I'm trying to add, but when I'm selecting a Job Function in the form, the field is not appearing in the form. Any thoughts? Thanks.

Flatten a JSON document using jq by filtering an array by keys

I have a JSON in the following format:
{
"subFields": [
{
"id": "question_1",
"type": "radioGroup",
"description": "Description1",
"title": "title1",
"subFields": [
{
"type": "radio",
"label": "Yes",
"value": 1
},
{
"type": "radio",
"label": "No",
"value": 0
},
{
"uiComponent": "SmallContent",
"componentProps": {
"text": "* If the answer to the above question is “Yes”, please contact the Support immediately."
}
}
]
},
{
"uiComponent": "Spacer"
},
{
"id": "question_2",
"type": "radioGroup",
"description": "Description2",
"title": "Title2",
"subFields": [
{
"type": "radio",
"label": "Label - Value 1",
"value": 1
},
{
"type": "radio",
"label": "Label - Value 2",
"value": 2
},
{
"type": "radio",
"label": "Label - Value 3",
"value": 3
},
{
"type": "radio",
"label": "Other",
"value": 13,
"subFields": [
{
"id": "question_2a",
"type": "string",
"condition": {
"type": "BinaryExpression",
"operator": "==",
"left": {
"type": "Identifier",
"name": "question_2"
},
"right": {
"type": "Literal",
"value": 13
}
}
}
]
}
]
},
{
"id": "question_2_b",
"style": {
"marginTop": "30px"
},
"type": "radioGroup",
"description": "Description3",
"title": "",
"subFields": [
{
"type": "radio",
"label": "Label - Radio 1",
"value": 1
},
{
"type": "radio",
"label": "Label - Radio 2",
"value": 2
},
{
"type": "radio",
"label": "Label - Radio 3",
"value": 3
}
]
},
{
"uiComponent": "Spacer"
},
{
"id": "question_3",
"type": "radioGroup",
"description": "Description3",
"title": "Title3",
"subFields": [
{
"type": "radio",
"label": "Yes",
"value": 1
},
{
"type": "radio",
"label": "No",
"value": 0
}
]
},
{
"uiComponent": "Spacer"
},
{
"condition": {
"type": "BinaryExpression",
"operator": "==",
"left": {
"type": "Identifier",
"name": "signer_type"
},
"right": {
"type": "Literal",
"value": "entity"
}
},
"subFields": [
{
"uiComponent": "Spacer"
},
{
"id": "question_4",
"type": "radioGroup",
"description": "Description_4",
"title": "Title_4",
"subFields": [
{
"type": "radio",
"label": "Yes",
"value": 1
},
{
"type": "radio",
"label": "No",
"value": 0
}
]
},
{
"uiComponent": "Spacer"
}
],
"uiComponent": "Block"
},
{
"uiComponent": "Spacer"
}
],
"uiComponent": "Container"
}
and I would like to generate the following output:
[
{
"id": "question_1",
"title": "title1",
"description": "Description1",
"type": "radioGroup",
"questions": "radio,Yes,1"
},
{
"id": "question_1",
"title": "title1",
"description": "Description1",
"type": "radioGroup",
"questions": "radio,No,0"
},
{
"id": "question_2",
"title": "Title2",
"description": "Description2",
"type": "radioGroup",
"questions": "radio,Label - Value 1,1"
},
{
"id": "question_2",
"title": "Title2",
"description": "Description2",
"type": "radioGroup",
"questions": "radio,Label - Value 2,2"
},
{
"id": "question_2",
"title": "Title2",
"description": "Description2",
"type": "radioGroup",
"questions": "radio,Label - Value 3,3"
},
{
"id": "question_2_b",
"title": "",
"description": "Description3",
"type": "radioGroup",
"questions": "radio,Label - Value 1,1"
},
{
"id": "question_2_b",
"title": "",
"description": "Description3",
"type": "radioGroup",
"questions": "radio,Label - Value 2,2"
},
{
"id": "question_2_b",
"title": "",
"description": "Description3",
"type": "radioGroup",
"questions": "radio,Label - Value 3,3"
},
{
"id": "question_3",
"title": "Title3",
"description": "Description3",
"type": "radioGroup",
"questions": "radio,Yes,1"
},
{
"id": "question_3",
"title": "Title3",
"description": "Description3",
"type": "radioGroup",
"questions": "radio,No,0"
}
]
or in alternative a reduced version:
[
"question_1",
"title1",
"Description1",
"radioGroup",
"radio,Yes,1",
"radio,No,0"
],
[
"question_2",
"title2",
"Description2",
"radioGroup",
"radio,Label - Value 1,1",
"radio,Label - Value 2,2",
"radio,Label - Value 3,3",
],
[
"question_2_b",
"Description3",
"radioGroup",
"radio,Label - Value 1,1",
"radio,Label - Value 2,2",
"radio,Label - Value 3,3",
],
[
"question_3",
"Title3",
"Description3",
"radioGroup",
"radio,Yes,1",
"radio,No,0"
]
The objective is to get only the objects that contain the id (to remove the {"uiComponent": "Spacer"} objects) and get only the subFields with these tags inside the array:
"subFields": [
{
"type": "xxxx",
"label": "xxxx",
"value": xxxx
},
I was able to flatten the JSON array by using the following JQ pattern:
jq play 1
.subFields[] | select(has("id") and .id != null)| {id: .id, type: .type, description: .description, anwers: .subFields}
and generated this result:
{
"id": "question_1",
"type": "radioGroup",
"description": "Description1",
"anwers": [
{
"type": "radio",
"label": "Yes",
"value": 1
},
{
"type": "radio",
"label": "No",
"value": 0
},
{
"uiComponent": "SmallContent",
"componentProps": {
"text": "* If the answer to the above question is “Yes”, please contact the Support immediately."
}
}
]
}
{
"id": "question_2",
"type": "radioGroup",
"description": "Description2",
"anwers": [
{
"type": "radio",
"label": "Label - Value 1",
"value": 1
},
{
"type": "radio",
"label": "Label - Value 2",
"value": 2
},
{
"type": "radio",
"label": "Label - Value 3",
"value": 3
},
{
"type": "radio",
"label": "Other",
"value": 13,
"subFields": [
{
"id": "question_2a",
"type": "string",
"condition": {
"type": "BinaryExpression",
"operator": "==",
"left": {
"type": "Identifier",
"name": "question_2"
},
"right": {
"type": "Literal",
"value": 13
}
}
}
]
}
]
}
{
"id": "question_2_b",
"type": "radioGroup",
"description": "Description3",
"anwers": [
{
"type": "radio",
"label": "Label - Radio 1",
"value": 1
},
{
"type": "radio",
"label": "Label - Radio 2",
"value": 2
},
{
"type": "radio",
"label": "Label - Radio 3",
"value": 3
}
]
}
{
"id": "question_3",
"type": "radioGroup",
"description": "Description3",
"anwers": [
{
"type": "radio",
"label": "Yes",
"value": 1
},
{
"type": "radio",
"label": "No",
"value": 0
}
]
}
My problem is that I don't know how to remove these sections:
{
"uiComponent": "SmallContent",
"componentProps": {
"text": "* If the answer to the above question is “Yes”, please contact the Support immediately."
}
}
and
"subFields": [
{
"id": "question_2a",
"type": "string",
"condition": {
"type": "BinaryExpression",
"operator": "==",
"left": {
"type": "Identifier",
"name": "question_2"
},
"right": {
"type": "Literal",
"value": 13
}
}
}
]
I played a little bit arround with this jq for the question_3 only:
jq play 2
.subFields[] | {id: .id, title: .title, description: .description, type: .type, subFields: .subFields} | select(has("id") and .id != null) | select(.id=="question_3") | {id: .id, title: .title, description: .description, type: .type, questions: (.subFields[]|join(","))}
and produced this result:
{
"id": "question_3",
"title": "Title3",
"description": "Description3",
"type": "radioGroup",
"questions": "radio,Yes,1"
}
{
"id": "question_3",
"title": "Title3",
"description": "Description3",
"type": "radioGroup",
"questions": "radio,No,0"
}
and also
jq play 3
.subFields[] | {id: .id, title: .title, description: .description, type: .type, subFields: .subFields} | select(has("id") and .id != null) | select(.id=="question_3") | [.id, .title, .description, .type, (.subFields[]|join(","))]
resulting on this:
[
"question_3",
"Title3",
"Description3",
"radioGroup",
"radio,Yes,1",
"radio,No,0"
]
Can you help me improve those JQ pattern I created to get the intended results?
Thanks in advance!
The following produces your first alternative:
.subFields[]
| select(.id?)
| { id, title, description, type} +
(.subFields[]
| select(.type?)
| [.type,.label,.value] | join(",")
| { questions: .} )
Notice the two select() filters.
The key names are specified explicitly here to ensure the ordering you specified is honored.

JMeter jp#gc JSON/YAML Path Assertion for an array

I'm trying to use jp#gc - JSON/YAML Path Assertion, when my Response Body is:
[
{
"label": "Alabama",
"value": "AL"
},
{
"label": "Alaska",
"value": "AK"
},
{
"label": "American Samoa",
"value": "AS"
},
{
"label": "Arizona",
"value": "AZ"
},
{
"label": "Arkansas",
"value": "AR"
},
{
"label": "California",
"value": "CA"
},
{
"label": "Colorado",
"value": "CO"
},
{
"label": "Connecticut",
"value": "CT"
},
{
"label": "Delaware",
"value": "DE"
},
{
"label": "District Of Columbia",
"value": "DC"
},
{
"label": "Federated States Of Micronesia",
"value": "FM"
},
{
"label": "Florida",
"value": "FL"
},
{
"label": "Georgia",
"value": "GA"
},
{
"label": "Guam",
"value": "GU"
},
{
"label": "Hawaii",
"value": "HI"
},
{
"label": "Idaho",
"value": "ID"
},
{
"label": "Illinois",
"value": "IL"
},
{
"label": "Indiana",
"value": "IN"
},
{
"label": "Iowa",
"value": "IA"
},
{
"label": "Kansas",
"value": "KS"
},
{
"label": "Kentucky",
"value": "KY"
},
{
"label": "Louisiana",
"value": "LA"
},
{
"label": "Maine",
"value": "ME"
},
{
"label": "Marshall Islands",
"value": "MH"
},
{
"label": "Maryland",
"value": "MD"
},
{
"label": "Massachusetts",
"value": "MA"
},
{
"label": "Michigan",
"value": "MI"
},
{
"label": "Minnesota",
"value": "MN"
},
{
"label": "Mississippi",
"value": "MS"
},
{
"label": "Missouri",
"value": "MO"
},
{
"label": "Montana",
"value": "MT"
},
{
"label": "Nebraska",
"value": "NE"
},
{
"label": "Nevada",
"value": "NV"
},
{
"label": "New Hampshire",
"value": "NH"
},
{
"label": "New Jersey",
"value": "NJ"
},
{
"label": "New Mexico",
"value": "NM"
},
{
"label": "New York",
"value": "NY"
},
{
"label": "North Carolina",
"value": "NC"
},
{
"label": "North Dakota",
"value": "ND"
},
{
"label": "Northern Mariana Islands",
"value": "MP"
},
{
"label": "Ohio",
"value": "OH"
},
{
"label": "Oklahoma",
"value": "OK"
},
{
"label": "Oregon",
"value": "OR"
},
{
"label": "Palau",
"value": "PW"
},
{
"label": "Pennsylvania",
"value": "PA"
},
{
"label": "Puerto Rico",
"value": "PR"
},
{
"label": "Rhode Island",
"value": "RI"
},
{
"label": "South Carolina",
"value": "SC"
},
{
"label": "South Dakota",
"value": "SD"
},
{
"label": "Tennessee",
"value": "TN"
},
{
"label": "Texas",
"value": "TX"
},
{
"label": "Utah",
"value": "UT"
},
{
"label": "Vermont",
"value": "VT"
},
{
"label": "Virgin Islands",
"value": "VI"
},
{
"label": "Virginia",
"value": "VA"
},
{
"label": "Washington",
"value": "WA"
},
{
"label": "West Virginia",
"value": "WV"
},
{
"label": "Wisconsin",
"value": "WI"
},
{
"label": "Wyoming",
"value": "WY"
}
]
Here is how is use the JSON/YAML Path Assertion:
but I'm getting Assertion failure:
The following setup should work for you:
More information:
JsonPath - Getting Started
Perl 5 Regex Cheat sheet
The New JSON/YAML Plugin - Using YAML in JMeter
Use JSON Assertion ( jp#gc - JSON/YAML is deprecated)
JSON start with array so use JSON Path
$.[0].label
You can also uncheck Match as regular expression

json - query with conditions

I have following json:
{
"id": "1",
"name": "profile1",
"userId": "0",
"groupId": "3",
"attributes": [
{
"id": "104",
"name": "Enable",
"value": "1"
},
{
"id": "105",
"name": "TargetNode",
"value": "system1"
},
{
"id": "106",
"name": "Timeout",
"value": "30"
}
],
"xconns": [
{
"id": "1",
"locked": false,
"attributeList": [
{
"id": "101",
"name": "Lgrp",
"value": "1"
},
{
"id": "102",
"name": "IsRem",
"value": "1"
},
{
"id": "103",
"name": "Media",
"value": "1"
}
]
},
{
"id": "1",
"locked": false,
"attributeList": [
{
"id": "101",
"name": "Lgrp",
"value": "1"
},
{
"id": "102",
"name": "IsRem",
"value": "1"
},
{
"id": "103",
"name": "Media",
"value": "1"
}
]
},
{
"id": "1",
"locked": false,
"attributeList": [
{
"id": "101",
"name": "Lgrp",
"value": "1"
},
{
"id": "102",
"name": "IsRem",
"value": "1"
},
{
"id": "103",
"name": "Media",
"value": "1"
}
]
}
]
}
{
"id": "2",
"name": "profile2",
"userId": "7",
"groupId": "0",
"attributes": [
{
"id": "104",
"name": "Enable",
"value": "1"
},
{
"id": "105",
"name": "TargetNode",
"value": "system2"
},
{
"id": "106",
"name": "Timeout",
"value": "30"
}
],
"xconns": [
{
"id": "2",
"locked": false,
"attributeList": [
{
"id": "101",
"name": "Lgrp",
"value": "1"
},
{
"id": "102",
"name": "IsRem",
"value": "1"
},
{
"id": "103",
"name": "Media",
"value": "1"
}
]
},
{
"id": "2",
"locked": false,
"attributeList": [
{
"id": "101",
"name": "Lgrp",
"value": "1"
},
{
"id": "102",
"name": "IsRem",
"value": "1"
},
{
"id": "103",
"name": "Media",
"value": "1"
}
]
},
{
"id": "2",
"locked": false,
"attributeList": [
{
"id": "101",
"name": "Lgrp",
"value": "1"
},
{
"id": "102",
"name": "IsRem",
"value": "1"
},
{
"id": "103",
"name": "Media",
"value": "1"
}
]
}
]
}
I can filter following:
$ jq -r 'select([.attributes[] | .name == "TargetNode" ] | any ) | [{userId, groupId, id, name}] | .[] | if (.userId == "0") then del(.userId) else . end | if (.groupId == "0") then del(.groupId) else . end | to_entries | map("\(.key | ascii_upcase):\(.value)") | #tsv' file.json
GROUPID:3 ID:1 NAME:profile1
USERID:7 ID:2 NAME:profile2
I need to add also value of TargetNode:
GROUPID:3 ID:1 NAME:profile1 TARGETNODE:system1
USERID:7 ID:2 NAME:profile2 TARGETNODE:system2
is there a way to include it in
[{userId, groupId, id, name, TargetNode}]
to get the value of TargetNode and not null?
GROUPID:3 ID:1 NAME:profile1 TARGETNODE:null
USERID:7 ID:2 NAME:profile2 TARGETNODE:null
Update:
the solution provided by RomanPerekhrest is nearly ok, but there is one issue because the json file in real is much bigger, there are more attrobutes in "main secttion", for example:
{
"id": "1",
"name": "profile1",
"userId": "0",
"groupId": "3",
"attrib101": "A",
"attrib102": "B",
"attributes": [
...
...
it is cousing that RomanPerekhrest's jq filter returns too much...
how to rid of them too?
ID:1 NAME:profile1 GROUPID:3 ATTRIB101:A ATTRIB102:B TARGETNODE:system1
ID:2 NAME:profile2 USERID:7 ATTRIB101:C ATTRIB102:D TARGETNODE:system2
jq solution:
jq -r '.attributes |= map(select(.name == "TargetNode"))
| if (.attributes | length != 0) then .targetNode = .attributes[0].value else . end
| if (.userId == "0") then del(.userId) else . end
| if (.groupId == "0") then del(.groupId) else . end
| del(.attributes, .xconns) | to_entries
| map("\(.key | ascii_upcase):\(.value)") | #tsv' file.json
If an object with "name": "TargetNode" pair not exists - TARGETNODE won't be added into resulting structure
The output:
ID:1 NAME:profile1 GROUPID:3 TARGETNODE:system1
ID:2 NAME:profile2 USERID:7 TARGETNODE:system2

Best way to flatten json

I have this awful looking JSON that is returned from the SugarCRM API.
What's the best approach to clean it up and remove the "name" key, and just have a single key and value (with no nested objects)
I wouldn't mind using the underscore library if needed.
{
"assigned_user_name": {
"name": "assigned_user_name",
"value": ""
},
"modified_by_name": {
"name": "modified_by_name",
"value": "Website Administrator"
},
"created_by_name": {
"name": "created_by_name",
"value": "Website Administrator"
},
"id": {
"name": "id",
"value": "6f9ec13f-dc29-ff18-da36-52d81a0076ad"
},
"name": {
"name": "name",
"value": " "
},
"date_entered": {
"name": "date_entered",
"value": "2014-01-16 17:45:33"
},
"date_modified": {
"name": "date_modified",
"value": "2014-01-16 17:45:33"
},
"modified_user_id": {
"name": "modified_user_id",
"value": "ab5ff74f-8043-f125-1409-523b6767fca9"
},
"created_by": {
"name": "created_by",
"value": "ab5ff74f-8043-f125-1409-523b6767fca9"
},
"description": {
"name": "description",
"value": ""
},
"deleted": {
"name": "deleted",
"value": "0"
},
"assigned_user_id": {
"name": "assigned_user_id",
"value": ""
},
"salutation": {
"name": "salutation",
"value": ""
},
"first_name": {
"name": "first_name",
"value": ""
},
"last_name": {
"name": "last_name",
"value": ""
},
"full_name": {
"name": "full_name",
"value": " "
},
"title": {
"name": "title",
"value": ""
},
"department": {
"name": "department",
"value": ""
},
"do_not_call": {
"name": "do_not_call",
"value": "0"
},
"phone_home": {
"name": "phone_home",
"value": ""
},
"email": {
"name": "email",
"value": ""
},
"phone_mobile": {
"name": "phone_mobile",
"value": ""
},
"phone_work": {
"name": "phone_work",
"value": ""
},
"phone_other": {
"name": "phone_other",
"value": ""
},
"phone_fax": {
"name": "phone_fax",
"value": ""
},
"email1": {
"name": "email1",
"value": "test#example.com"
},
"email2": {
"name": "email2",
"value": ""
},
"invalid_email": {
"name": "invalid_email",
"value": "0"
},
"email_opt_out": {
"name": "email_opt_out",
"value": "0"
},
"primary_address_street": {
"name": "primary_address_street",
"value": ""
},
"primary_address_street_2": {
"name": "primary_address_street_2",
"value": ""
},
"primary_address_street_3": {
"name": "primary_address_street_3",
"value": ""
},
"primary_address_city": {
"name": "primary_address_city",
"value": ""
},
"primary_address_state": {
"name": "primary_address_state",
"value": ""
},
"primary_address_postalcode": {
"name": "primary_address_postalcode",
"value": ""
},
"primary_address_country": {
"name": "primary_address_country",
"value": ""
},
"alt_address_street": {
"name": "alt_address_street",
"value": ""
},
"alt_address_street_2": {
"name": "alt_address_street_2",
"value": ""
},
"alt_address_street_3": {
"name": "alt_address_street_3",
"value": ""
},
"alt_address_city": {
"name": "alt_address_city",
"value": ""
},
"alt_address_state": {
"name": "alt_address_state",
"value": ""
},
"alt_address_postalcode": {
"name": "alt_address_postalcode",
"value": ""
},
"alt_address_country": {
"name": "alt_address_country",
"value": ""
},
"assistant": {
"name": "assistant",
"value": ""
},
"assistant_phone": {
"name": "assistant_phone",
"value": ""
},
"email_and_name1": {
"name": "email_and_name1",
"value": ""
},
"lead_source": {
"name": "lead_source",
"value": ""
},
"opportunity_role_fields": {
"name": "opportunity_role_fields",
"value": ""
},
"opportunity_role_id": {
"name": "opportunity_role_id",
"value": ""
},
"opportunity_role": {
"name": "opportunity_role",
"value": ""
},
"reports_to_id": {
"name": "reports_to_id",
"value": ""
},
"report_to_name": {
"name": "report_to_name",
"value": ""
},
"birthdate": {
"name": "birthdate",
"value": false
},
"campaign_id": {
"name": "campaign_id",
"value": ""
},
"campaign_name": {
"name": "campaign_name",
"value": ""
},
"c_accept_status_fields": {
"name": "c_accept_status_fields",
"value": ""
},
"m_accept_status_fields": {
"name": "m_accept_status_fields",
"value": ""
},
"accept_status_id": {
"name": "accept_status_id",
"value": ""
},
"accept_status_name": {
"name": "accept_status_name",
"value": ""
},
"sync_contact": {
"name": "sync_contact",
"value": ""
},
"event_contact_fields": {
"name": "event_contact_fields",
"value": ""
},
"event_contact_id": {
"name": "event_contact_id",
"value": ""
},
"event_status": {
"name": "event_status",
"value": ""
},
"cc_sync": {
"name": "cc_sync",
"value": "0"
},
"cc_id": {
"name": "cc_id",
"value": ""
},
"cc_lists": {
"name": "cc_lists",
"value": ""
},
"cc_lists_view": {
"name": "cc_lists_view",
"value": ""
},
"cc_optout": {
"name": "cc_optout",
"value": "0"
},
"mc_expires_c": {
"name": "mc_expires_c",
"value": false
},
"birthyear_c": {
"name": "birthyear_c",
"value": ""
},
"contact_id_c": {
"name": "contact_id_c",
"value": ""
},
"currency_id": {
"name": "currency_id",
"value": ""
},
"employer_c": {
"name": "employer_c",
"value": ""
},
"employer_website_c": {
"name": "employer_website_c",
"value": ""
},
"fico_score_c": {
"name": "fico_score_c",
"value": ""
},
"household_income_c": {
"name": "household_income_c",
"value": ""
},
"investment_capital_c": {
"name": "investment_capital_c",
"value": ""
},
"job_title_c": {
"name": "job_title_c",
"value": ""
},
"mbrs_company_c": {
"name": "mbrs_company_c",
"value": ""
},
"membr_type_c": {
"name": "membr_type_c",
"value": ""
},
"nickname_c": {
"name": "nickname_c",
"value": ""
},
"num_properties_financed_c": {
"name": "num_properties_financed_c",
"value": ""
},
"num_properties_owned_c": {
"name": "num_properties_owned_c",
"value": ""
},
"own_primary_residence_c": {
"name": "own_primary_residence_c",
"value": ""
},
"parent_id": {
"name": "parent_id",
"value": ""
},
"parent_name": {
"name": "parent_name",
"value": ""
},
"parent_type": {
"name": "parent_type",
"value": ""
},
"planned_retirement_date_c": {
"name": "planned_retirement_date_c",
"value": false
},
"realestateadvisor_c": {
"name": "realestateadvisor_c",
"value": ""
},
"referral_c": {
"name": "referral_c",
"value": ""
},
"sdira_c": {
"name": "sdira_c",
"value": ""
},
"self_directed_ira_c": {
"name": "self_directed_ira_c",
"value": ""
},
"self_directed_ira_capital_c": {
"name": "self_directed_ira_capital_c",
"value": ""
},
"source_c": {
"name": "source_c",
"value": ""
},
"source_sub_c": {
"name": "source_sub_c",
"value": ""
},
"spouse_c": {
"name": "spouse_c",
"value": ""
},
"user_id1_c": {
"name": "user_id1_c",
"value": ""
},
"user_id_c": {
"name": "user_id_c",
"value": ""
},
"usigndate_c": {
"name": "usigndate_c",
"value": ""
},
"usign_c": {
"name": "usign_c",
"value": ""
},
"longitude_c": {
"name": "longitude_c",
"value": ""
},
"latitude_c": {
"name": "latitude_c",
"value": ""
},
"newmemberform_c": {
"name": "newmemberform_c",
"value": ""
},
"nr_contact_lead_source_c": {
"name": "nr_contact_lead_source_c",
"value": ""
},
"nr_contact_lead_score_c": {
"name": "nr_contact_lead_score_c",
"value": ""
},
"nr_contact_recent_activity_c": {
"name": "nr_contact_recent_activity_c",
"value": ""
}
}
If you want to use Underscore then reduce will do the trick:
var o = _(ugly).reduce(function(m, h) {
m[h.name] = h.value;
return m;
}, { });
Demo: http://jsfiddle.net/ambiguous/mE56S/
I'd just use a straight forward approach:
var newArr = {};
for(var key in YOUR_JSON_ARRAY)
newArr[key] = YOUR_JSON_ARRAY[key].value;
Keep in mind that the convention in the vardef array is to have the array indices be the field names, but it's not mandatory. I can't think of an example where they're not the same, but you could create a field with an array like 'my_new_field' => array('name'=>'new_field_c') and it would work.