โ10-31-2017 01:11 PM
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
Solved! Go to Solution.
โ11-01-2017 07:51 AM
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)
โ10-31-2017 10:21 PM
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.
โ11-01-2017 07:51 AM
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)
โ11-02-2017 05:43 AM
this really helps. Thanks