cancel
Showing results forย 
Search instead forย 
Did you mean:ย 

Json transformation

walkerline117
Contributor

Ok, here is the original Json

{
โ€œdocsโ€: [
{
โ€œtitleโ€: โ€œdoc1โ€,
โ€œdescriptionโ€: โ€œdoc1 descriptionโ€,
โ€œattachment_extension_typeโ€: [
โ€œpdfโ€
],
โ€œattachment_nameโ€: [
โ€œ712210 Regulation Thats Good for Competition.pdfโ€
],
โ€œattachment_name_pdf_flagโ€: [
โ€œNโ€
],
โ€œattachment_sizeโ€: [
โ€œ510230โ€
],
โ€œattachment_titleโ€: [
โ€œQuarterly articleโ€
],
โ€œattachment_r_object_idโ€: [
โ€œ0f9ea5bf-10fd-427d-8d34-f8fe4a30d591โ€
],
โ€œattachment_order_noโ€: [
โ€œ0โ€
],
โ€œauthors_person_idโ€: [
โ€œ1954โ€,
โ€œ4547โ€
],
โ€œauthors_fmnoโ€: [
โ€œ1957โ€,
โ€œ4565โ€
],
โ€œauthors_first_nameโ€: [
โ€œDianaโ€,
โ€œScottโ€
],
โ€œauthors_preferred_nameโ€: [
โ€œDianaโ€,
โ€œScottโ€
],
โ€œauthors_last_nameโ€: [
โ€œFarrellโ€,
โ€œBeardsleyโ€
],
โ€œauthors_vendor_idโ€: [
โ€œ11854โ€,
โ€œ14447โ€
],
โ€œauthors_statusโ€: [
โ€œAlumniโ€,
โ€œAlumniโ€
],
โ€œauthors_show_alumni_flagโ€: [
โ€œYโ€,
โ€œNโ€
],
โ€œauthors_deceased_flagโ€: [
โ€œNโ€,
โ€œNโ€
],
โ€œtimestampโ€: โ€œ2017-07-24T15:02:19.158Zโ€,
โ€œno_of_docsโ€: 0,
โ€œproject_idโ€: 0
}

And here is the output we want

โ€œdocsโ€: {
โ€œdescriptionโ€: โ€œdoc1 descriptionโ€,
โ€œtitleโ€: โ€œdoc1โ€,
โ€œauthoredDateโ€: โ€œ2005-06-15T16:25:15Zโ€,
โ€œattachmentsโ€: [
{
โ€œnameโ€: โ€œ712210 Regulation Thats Good for Competition.pdfโ€,
โ€œsizeโ€: 510230,
โ€œorderNoโ€: 0,
โ€œpdfFlagโ€: false,
โ€œobjectIdโ€: โ€œ0f9ea5bf-10fd-427d-8d34-f8fe4a30d591โ€,
โ€œtitleโ€: โ€œQuarterly articleโ€,
โ€œextensionTypeโ€: โ€œpdfโ€
}
],
โ€œauthorsโ€: [
{
โ€œfirstNameโ€: โ€œDianaโ€,
โ€œlastNameโ€: โ€œFarrellโ€,
โ€œstatusโ€: โ€œAlumniโ€,
โ€œpersonIdโ€: 1954,
โ€œpreferredNameโ€: โ€œDianaโ€,
โ€œdeceasedFlagโ€: false,
โ€œshowAlumniFlagโ€: โ€œYโ€,
โ€œvendorIdโ€: 11854
},
{
โ€œfirstNameโ€: โ€œScottโ€,
โ€œlastNameโ€: โ€œBeardsleyโ€,
โ€œstatusโ€: โ€œAlumniโ€,
โ€œpersonIdโ€: 4547,
โ€œpreferredNameโ€: โ€œScottโ€,
โ€œdeceasedFlagโ€: false,
โ€œshowAlumniFlagโ€: โ€œYโ€,
โ€œvendorIdโ€: 14447
}
]
}
}

How I can do such transformation for a ULTRA task?
Any suggestions?

Thanks

1 ACCEPTED SOLUTION

tstack
Former Employee

Thereโ€™s a lot going on here, so letโ€™s break it down into several steps:

The first thing I notice is that the values for each property are grouped together in arrays. For example:

    "authors_fmno": [
        "1957",
        "4565"
    ],
    "authors_first_name": [
        "Diana",
        "Scott"
    ],

This grouping is a sign that the sl.zip() function should be used. This function will group together the elements in the arrays. Doing this manually with sl.zip($authors_fmno, $authors_first_name) should return the following:

[
    ["1957", "Diana"],
    ["4565", "Scott"]
]

That should take care of one of the more complicated parts of the transform. However, you probably donโ€™t want to manually go through each property, so we need a way to mix in the property names into the values. Once the property names are mixed in, we can construct the objects using the extend() method. The mapValues() can help with mixing in the names since it can walk through the properties in an object and transform the values using a callback function. The following callback will transform the value of any property that starts with โ€œauthors_โ€. Note that we have to do a map() on the array value to mix in the name for every element.

(value, key) => key.startsWith("authors_") ? value.map(x => [key, x]) : value

Now that we have the callback, we need to do the mapValues() call. Note that Iโ€™ve tweaked the key name to remove the โ€œauthors_โ€ prefix and Iโ€™ve setup the Mapper with a โ€œMapping Rootโ€ of โ€œ$docs[*]โ€ so that all elements of the docs array are transformed.

$.mapValues((value, key) => key.startsWith("authors_") ? value.map(x => [key.replace(/^authors_/, ''), x]) : value)

The mapValues() result will still be an object, so we need to get the property values into an array to feed to the extend() method. The jsonPath() function can do that and filter for only the properties with the โ€œauthors_โ€ prefix:

jsonPath($, "$[?(key.startsWith('authors_'))]")

At this point, we have the data in a structure that we can feed into the sl.zip() function.

sl.zip.apply(null, jsonPath($, "$[?(key.startsWith('authors_'))]"))

Note that we have to use apply() since sl.zip() expects each array to be passed as a parameter. The apply() function will call the function and pass the array as the arguments to the function.
In the 4.11 release, you can use the spread operator (โ€ฆ) instead:

sl.zip(...jsonPath($, "$[?(key.startsWith('authors_'))]")).map(x => {}.extend(x))

The result of the sl.zip() function will be another array, so we need to map() that to transform each element from an array to an object with the extend() method:

sl.zip.apply(null, jsonPath($, "$[?(key.startsWith('authors_'))]")).map(x => {}.extend(x))

Hereโ€™s a pipeline export that demonstrates all of this:

JsonTransformation_2017_11_01.slp (5.2 KB)

View solution in original post

3 REPLIES 3

robin
Former Employee

Hi, just had a quick look at the above. It looks like the original structure defines related information about by the index position in the respective array. So the first value of each of the authors_preferred_name, authors_last_name etc. should be grouped together into the same object in the targeted structure. Similarly for the second, as so on. Itโ€™s further complicated by this rule applying separately for attachments and authors (and perhaps others too).

My first thought would be to look into using the Mapper and the expression languageโ€™s reduce() function for Arrays.

Itโ€™s possible that point you in the right direction.

tstack
Former Employee

Thereโ€™s a lot going on here, so letโ€™s break it down into several steps:

The first thing I notice is that the values for each property are grouped together in arrays. For example:

    "authors_fmno": [
        "1957",
        "4565"
    ],
    "authors_first_name": [
        "Diana",
        "Scott"
    ],

This grouping is a sign that the sl.zip() function should be used. This function will group together the elements in the arrays. Doing this manually with sl.zip($authors_fmno, $authors_first_name) should return the following:

[
    ["1957", "Diana"],
    ["4565", "Scott"]
]

That should take care of one of the more complicated parts of the transform. However, you probably donโ€™t want to manually go through each property, so we need a way to mix in the property names into the values. Once the property names are mixed in, we can construct the objects using the extend() method. The mapValues() can help with mixing in the names since it can walk through the properties in an object and transform the values using a callback function. The following callback will transform the value of any property that starts with โ€œauthors_โ€. Note that we have to do a map() on the array value to mix in the name for every element.

(value, key) => key.startsWith("authors_") ? value.map(x => [key, x]) : value

Now that we have the callback, we need to do the mapValues() call. Note that Iโ€™ve tweaked the key name to remove the โ€œauthors_โ€ prefix and Iโ€™ve setup the Mapper with a โ€œMapping Rootโ€ of โ€œ$docs[*]โ€ so that all elements of the docs array are transformed.

$.mapValues((value, key) => key.startsWith("authors_") ? value.map(x => [key.replace(/^authors_/, ''), x]) : value)

The mapValues() result will still be an object, so we need to get the property values into an array to feed to the extend() method. The jsonPath() function can do that and filter for only the properties with the โ€œauthors_โ€ prefix:

jsonPath($, "$[?(key.startsWith('authors_'))]")

At this point, we have the data in a structure that we can feed into the sl.zip() function.

sl.zip.apply(null, jsonPath($, "$[?(key.startsWith('authors_'))]"))

Note that we have to use apply() since sl.zip() expects each array to be passed as a parameter. The apply() function will call the function and pass the array as the arguments to the function.
In the 4.11 release, you can use the spread operator (โ€ฆ) instead:

sl.zip(...jsonPath($, "$[?(key.startsWith('authors_'))]")).map(x => {}.extend(x))

The result of the sl.zip() function will be another array, so we need to map() that to transform each element from an array to an object with the extend() method:

sl.zip.apply(null, jsonPath($, "$[?(key.startsWith('authors_'))]")).map(x => {}.extend(x))

Hereโ€™s a pipeline export that demonstrates all of this:

JsonTransformation_2017_11_01.slp (5.2 KB)

this really helps. Thanks