Groovy: Convert Json to Text

Asked by At

Would like to convert the below json record into a text using Groovy

import groovy.json.*

def js = """{
  "title": {
    "titleid": "222",
    "titlename": "ABCD",
    "titledesc": null
  },
  "customer": {
    "customerDetail": {
      "customerid": 878378743,
      "customerstatus": "ACTIVE",
      "customersystems": {
        "customersystem1": "SYS01",
        "customersystem2": null
      },
      "sysid": null
    },
    "store": {
      "storeid": "LOS002",
      "storename": "LAStore",
      "areacode": "JDHJ8K988"
    },
    "persons": {
      "person1": {
        "personid": "123",
        "personname": "IIISKDJKJSD"
      },
      "person2": {
        "personid": "456",
        "personname": "IUDFIDIKJK"
      }
    },
    "order": {
      "orderdetail": {
        "orderid": "4291026",
        "ordername": "ORD93999"
      }
    },
    "product": {
      "orderdate": "20190101",
      "currency": "USD",
      "amount": 1000.23
    }
  }
}  
"""

def data = new JsonSlurper().parseText(js)  

Expected output should as below with proper header names:

customerId,customerstatus,customersystem1,sysid,storeid,storename,person1.personid,person1.personname,orderid,orderdate,currency,amount,titlename
878378743,ACTIVE,SYS01,null,LOS002,LAStore,123,IIISKDJKJSD,4291026,20190101,USD,1000.23

This is just a single json record so how would I convert all my json records using Groovy?

1 Answers

2
Matias Bjarland On Best Solutions

The following code:

import groovy.json.*

def js = """
[
{
  "title": {
    "titleid": "222",
    "titlename": "ABCD",
    "titledesc": null
  },
  "customer": {
    "customerDetail": {
      "customerid": 878378743,
      "customerstatus": "ACTIVE",
      "customersystems": {
        "customersystem1": "SYS01",
        "customersystem2": null
      },
      "sysid": null
    },
    "store": {
      "storeid": "LOS002",
      "storename": "LAStore",
      "areacode": "JDHJ8K988"
    },
    "persons": {
      "person1": {
        "personid": "123",
        "personname": "IIISKDJKJSD"
      },
      "person2": {
        "personid": "456",
        "personname": "IUDFIDIKJK"
      }
    },
    "order": {
      "orderdetail": {
        "orderid": "4291026",
        "ordername": "ORD93999"
      }
    },
    "product": {
      "orderdate": "20190101",
      "currency": "USD",
      "amount": 1000.23
    }
  }
}
]  
"""

/* 
customerId,customerstatus,customersystem1,sysid,storeid,storename,person1.personid,person1.personname,orderid,orderdate,currency,amount,titlename
878378743,ACTIVE,SYS01,null,LOS002,LAStore,123,IIISKDJKJSD,4291026,20190101,USD,1000.23
*/

def data = new JsonSlurper().parseText(js)  
def mappings = [ 
  customerId:            { n -> n.customer.customerDetail.customerid }, 
  customerstatus:        { n -> n.customer.customerDetail.customerstatus }, 
  customersystem1:       { n -> n.customer.customerDetail.customersystems.customersystem1 }, 
  sysid:                 { n -> n.customer.customerDetail.sysid }, 
  storeid:               { n -> n.customer.store.storeid }, 
  storename:             { n -> n.customer.store.storename }, 
  'person1.personid':    { n -> n.customer.persons.person1.personid }, 
  'person1.personname':  { n -> n.customer.persons.person1.personname }, 
  orderid:               { n -> n.customer.order.orderdetail.orderid }, 
  orderdate:             { n -> n.customer.product.orderdate }, 
  currency:              { n -> n.customer.product.currency }, 
  amount:                { n -> n.customer.product.amount }, 
  titlename:             { n -> n.title.titlename } 
]

def headers = mappings.keySet().join(',') //edited thanks to comment

println headers
data.each { item ->
  def row = mappings.collect { k, v -> v(item) }.join(',')
  println row
}

does what you ask for. Note that I made the json be a list of items instead of the single item since it seemed from your text that that is what you were after.

Running the above code produces:

~> groovy solution.groovy
customerId,customerstatus,customersystem1,sysid,storeid,storename,person1.personid,person1.personname,orderid,orderdate,currency,amount,titlename
878378743,ACTIVE,SYS01,null,LOS002,LAStore,123,IIISKDJKJSD,4291026,20190101,USD,1000.23,ABCD
~> 

note that if this is going into some critical system and is not just a one-off ad-hoc piece of code, you should probably do things like check the return value of v(item) and log some error of otherwise handle when there is no value for a certain path in the json etc.

Should also be noted that the above code relies on the fact that a map literal in groovy (i.e. def mappings = [:]) creates an instance of java's LinkedHashMap which has predictable iteration order for things like keySet() and collect { }.

<< edit >>

For a single item json blob, you would change the code as follows:

def js = """
{
...
}
"""

def item = new JsonSlurper().parseText(js) 
def mappings = ...

def headers = mappings.keySet().join(',') //edited thanks to comment
println headers

def row = mappings.collect { k, v -> v(item) }.join(',')
println row    

where ... denotes that the block is unchanged from the example above.