Flatten JSON files into CSV files
Created by @schelluri The pipeline pattern flattens a JSON file, which has multiple objects, and turns it into a CSV file. Configuration Sources: JSON Generator Targets: CSV file Snaps used: JSON Generator, JSON Formatter, JSON Parser, Script, CSV Formatter, File Writer Downloads MS_Flatten_Script.slp (31.4 KB)7.4KViews1like2CommentsRemote file renaming/moving
Hi, I have a requirement to push a file to SFTP server. But since the file is quite large and to avoid race condition (we writing and remote function reading at the same time) we like to write the file with different extension or to a temp folder in remote server and them rename or move the file at the server. None for the File snaps support these feature. Could you please help me identify a way around to address above problem.7.4KViews1like13CommentsGenerate dynamic HTML file in snaplogic
Hi All, Have a question: I have a Script file that generates a dynamic html file. And this dynamic html file generated is fed into EMAIL SENDER snap. Problem: I want to place my script file inside snaplogic directly. Unable to achieve this. I am pasting my script here: script.txt (10.4 KB) If any one can help me how to place the script code into snaplogic. Tried using script snap but was unable to make it work. Any help would be much appreciated.Solved4.5KViews0likes5CommentsScript Snap Limit of 50 Documents?
I’m working on transforming some data that’s coming in from a REST GET Snap. The format of the data that is being returned is quite disjointed. Essentially, the headers come in one of the JSON elements, and the data comes in another set. I have to marry the two together in SnapLogic. I have successfully written a script that loops through each of the “rows”, and pairs the data with the appropriate header. I have accomplished this in two different ways. I have created a script that outputs just one document, with an array of the responses. I have also created another version of the script that outputs each row as its own document. #2 seems to be the best approach here, as downstream snaps can handle the data without any problems. It looks great. But I’m running into a limitation that doesn’t make sense. I can only output 50 documents? If I attempt anything more, the Snap throws an error. I just don’t understand this limitation? What is the correct approach to work on larger datasets if the Script Snap limits me so heavily? #1 works well too, except for the fact that the Script Snap outputs the rows as an Object, and I can’t use the JSON Splitter Snap to split the object (which is truly just an Array) up. So I’m kinda stuck here. I’m sure I could devise some tricky workaround to split up the rows, and essentially execute the same Script Snap multiple times, but that seems kludgy at best. What’s the best practice here, and why am I so limited to outputting only 50 documents? Thanks in advance.Solved4.1KViews0likes3CommentsCount number of records fetched/processed from a flat file/upstream system systems (snowflake, salesforce, oracle)/file writer without using a pipeline execute
Hi Team, I’m looking to count records on a couple of scenarios listed below: (1) Records fetched from a flat file (e.g. excel, csv) and writing the total counts of records into a new column e.g. File Reader --> Mapper (transformation rules here with new column added to count the total number of records) --> Excel/CSV formatter --> File Writer I’ve tried using snap.in.totalCount and snap.outputViews inside a mapper but didn’t get the expected results. (2) Records fetched from source system like snowflake, salesforce, oracle, etc. without using a count command in the query itself I’m thinking of using a Group By or an Aggregate snap to get the counts, would that be the right approach? (3) Counting number of records processed after the operation has been completed. For instance, I’m writing a flat file (excel/csv) but want a new column ingested into that file dynamically that states the total number of docs processed AND send an email to the team that states total number of docs processed. e.g. File Reader/Salesforce Read --> Mapper --> excel/csv formatter --> File Writer --> Mapper (anticipating this should have some rules) --> Email Sender (sends count ONLY) Thanking you in advance for your time and help on this one. Best Regards, DarshSolved6.5KViews0likes2CommentsJavaScript Function Scoping (Script Snap)
I thought about creating a ticket to ask this, then realized others probably could use this information as well… When writing a script for a JavaScript snap, one can define all the subroutines as member functions within the “impl” object: var impl = { input: input, output: output, error: error, log: log, // A real function would do a lot more than this doSomething: function( inputVal ) { return inputVal; }, execute: function() { while (this.input.hasNext()) { var doc = this.input.next(); ... var foo = this.doSomething(doc.baz); ... var wrapper = new java.util.HashMap(); wrapper.put("original", doc); this.output.write(doc, wrapper); } } }; However, some developers prefer making functions stand by themselves when they do not access other members of the object (thus, not needing to be a member themselves): // A real function would do a lot more than this function doSomething( inputVal ) { return inputVal; }; var impl = { input: input, output: output, error: error, log: log, execute: function() { while (this.input.hasNext()) { var doc = this.input.next(); ... var foo = doSomething(doc.baz); ... var wrapper = new java.util.HashMap(); wrapper.put("original", doc); this.output.write(doc, wrapper); } } }; My Question: In terms of scoping (and memory usage), is there any difference between the two? Particularly if there are multiple script snaps running at the same time in the same pipeline? For example, suppose you have two script snaps, Script-1 and Script-2: Clearly, var impl is a separate instance in each, otherwise you couldn’t have two script snaps in the same pipeline. If each snap has it’s own separate function doSomething() in the separate scripts, I’m assuming those are also outside of each other’s scope, is that correct? Since functions are first-class objects in JavaScript, does it consume more memory to make the functions external to the impl object, than to have them as members? Inquiring minds want to know!2.3KViews0likes0CommentsPowershell command execute Snap
Hi, Is there any way to execute a command line scripts (Ex: Power shell)? Our scenario is to execute a set of commands (which is located over in a server, where we could establish a connection through an FTP/SFTP) at the end of load completion for an UI Refresh, please advise if there is any direct way or just let us know any workaround!! Thanks, Aravind6.5KViews0likes7CommentsConfiguring the Script Snap to use a configured HTTP proxy environment variable
HTTP-compatible Snap Packs can leverage an HTTP proxy configured in the Snaplex’s Network Proxies configuration tab within the SnapLogic Manager web application. However, the Script Snap is different because you can write Scripts to call external processes (e.g. curl) and these will not be aware of any proxy configuration set within the SnapLogic application. curl can be configured to use a proxy directly via the --proxy argument, but if you wished to enforce that proxy usage across all usages of the Script Snap, you can set the http_proxy and/or https_proxy environment variables within a special file - /etc/sysconfig/jcc . Environment variables declared within this file will be visible to the Snaplex application (OS-level env vars will not be). This file (and directory) may not exist in your Snaplex, so you may have to create them (similar to the instructions on the Configuring a custom JRE version page): sudo mkdir -p /etc/sysconfig; sudo sh -c "echo 'export http_proxy=username:password@proxy-ip-address:port' >> /etc/sysconfig/jcc" substituting the equivalent values for username/password (if authentication is required), proxy-ip-address , and port (you may also want to add https_proxy too). Once this file is created, restart the Snaplex application ( /opt/snaplogic/bin/jcc.sh restart or c:\opt\snaplogic\bin\jcc.bat restart ) and the http_proxy / https_proxy environment variable will now be active within the SnapLogic product. Assuming your proxy is correctly configured, you can then run your Script that calls the external process and, if the process supports using a proxy, it will respect the setting. For example, the following Script Snap (Python) uses the subprocess library to execute curl and adds the response body to the output document. # Import the interface required by the Script snap. from com.snaplogic.scripting.language import ScriptHook import subprocess class TransformScript(ScriptHook): def __init__(self, input, output, error, log): self.input = input self.output = output self.error = error self.log = log # The "execute()" method is called once when the pipeline is started # and allowed to process its inputs or just send data to its outputs. def execute(self): self.log.info("Executing Transform script") while self.input.hasNext(): try: # Read the next input document, store it in a new dictionary, and write this as an output document. inDoc = self.input.next() proc = subprocess.Popen(['curl','https://www.snaplogic.com'], stdout=subprocess.PIPE) (out, err) = proc.communicate() outDoc = { 'original' : out } self.output.write(inDoc, outDoc) except Exception as e: errDoc = { 'error' : str(e) } self.log.error("Error in python script") self.error.write(errDoc) self.log.info("Script executed") # The "cleanup()" method is called after the snap has exited the execute() method def cleanup(self): self.log.info("Cleaning up") # The Script Snap will look for a ScriptHook object in the "hook" # variable. The snap will then call the hook's "execute" method. hook = TransformScript(input, output, error, log) On execution, the proxy access log should show the request being routed through the proxy.5.1KViews0likes2CommentsScript help
Hello All, There is log file writting during execution of SnapLogic pipeline, as we dont have direct access so wanted to browse below directory from script snap. Can anyone help me here. Below is the javascript used for writ the logs:- try { load(“nashorn:mozilla_compat.js”); } catch (e) { } var impl = { input: input, output: output, error: error, log: log, execute: function () { while (this.input.hasNext()) { var doc = this.input.next(); this.output.write(doc, doc.response); var lastSystemTime = doc.lastSystemTime; var wrapper = new java.util.HashMap(); wrapper.putAll(doc); wrapper.remove("lastSystemTime"); var externalSystem = wrapper.externalSystem; if ((externalSystem != null) && (externalSystem.length > 0)) { if (! externalSystem[externalSystem.length - 1].endTime) { externalSystem[externalSystem.length - 1].endTime = lastSystemTime; } } wrapper.put("success", false); try { var om = new ObjectMapper(); om.writeValue(new java.io.File("/tmp/API_LOG/" + doc.executionId), wrapper); } catch (e) {} } } }; importPackage(com.snaplogic.scripting.language); importPackage(java.util.HashMap); importPackage(“com.fasterxml.jackson.databind”); importPackage(java.io.File); var hook = new com.snaplogic.scripting.language.ScriptHook(impl); Can any onne help me here to read above directory or files ?? Thanks in advanced.2.7KViews0likes2CommentsScript Snap Error: "[object JavaPackage] is not a Java class in nashorn:mozilla_compat.js"
I have a script snap that I’m using to do some weird data manipulation to amalgamate 3-hourly data and 1-hourly data into a consistent 1-hourly format. Here is my script, I’m using javascript code: // Ensure compatibility with both JDK 7 and 8 JSR-223 Script Engines try { load("nashorn:mozilla_compat.js"); } catch (e) { } // Import the interface required by the Script snap. importPackage(com.snaplogic.scripting.language); // Import the serializable Java type we'll use for the output data. importClass(java.util.Array); /** * Create an object that implements the methods defined by the "ScriptHook" * interface. We'll be passing this object to the constructor for the * ScriptHook interface. */ var impl = { /* * These variables (input, output, error, log) are defined by the * ExecuteScript snap when evaluating this script. */ input: input, output: output, error: error, log: log, /** * The "execute()" method is called once when the pipeline is started * and allowed to process its inputs or just send data to its outputs. * * Exceptions are automatically caught and sent to the error view. */ execute: function () { this.log.info("Executing Transform Script"); while (this.input.hasNext()) { try { // Read the next input document, store it a new LinkedHashMap, and write this as an output document. // We must use a serializable Java type liked LinkedHashMap for each output instead of a native // JavaScript object so that downstream Snaps like Copy can process it correctly. var inDoc = this.input.next(); var outDoc = new Array(); var earliestTime = new Date(inDoc.original.start_date); var latestTime = new Date(inDoc.original.end_date); var forecasts = []; for (var i = 0; i < inDoc.entity.forecasts.arrayLength; i++) { var forecast = inDoc.entity.forecasts[i]; forecast.validFromDate = new Date(forecast.validFrom); forecast.validUntilDate = new Date(forecast.validUntil); forecasts.push(forecast); } var checkingTime = earliestTime; do { var outputObj = { weatherDate: checkingTime, weatherData: {} }; var validPt0s = {}; var validPt1h = {}; var validPt3h = {}; for (var i = 0; i < forecasts.arrayLength; i++) { var forecast = forcasts[i]; if (forecast.validFromDate <= checkingTime && forecast.validUntilDate >= checkingTime) { // 1) get the first valid PT0S result if (forecast.validPeriod === "PT0S" && !validPt0s) { validPt0s = forecast; outputObj.weatherData.airTemperatureInCelsius = validPt0s.airTemperatureInCelsius; continue; } // 2) get the first valid PT1H result if (forecast.validPeriod === "PT1H" && !validPt1h) { validPt1h = forecast; outputObj.weatherData.precipitationAmountInMillimeter = validPt1h.precipitationAmountInMillimeter; outputObj.weatherData.netRadiationInJoulePerCentimeterSquare = validPt1h.netRadiationInJoulePerCentimeterSquare; continue; } // 3) get the first valid PT3H result if (forecast.validPeriod === "PT3H" && !validPt3h) { validPt3h = forecast; outputObj.weatherData.averageWindSpeedInKnots = validPt3h.averageWindSpeedInKnots; continue; } } } outDoc.push(outputObj); checkingTime.setMinutes(checkingTime.getMinutes() + 60); } while (checkingTime <= latestTime) this.output.write(inDoc, outDoc); } catch (err) { var errDoc = new LinkedHashMap(); errDoc.put("error", err); this.log.error(err); this.error.write(errDoc); } } this.log.info("Script executed"); }, /** * The "cleanup()" method is called after the snap has exited the execute() method */ cleanup: function () { this.log.info("Cleaning up") } }; /** * The Script Snap will look for a ScriptHook object in the "hook" * variable. The snap will then call the hook's "execute" method. */ var hook = new com.snaplogic.scripting.language.ScriptHook(impl); The error I’m seeing is: Failure: Cannot evaluate Script file: <WHOLE SCRIPT HERE>, Reason: TypeError: [object JavaPackage] is not a Java class in nashorn:mozilla_compat.js at line number 375 at column number 16, Resolution: Please fix the script file error at line: 375 column: 16 Since the error is pointing somewhere other than my code, is there something that needs to be installed on our own workers? Is this just a misleading error and there is something wrong with my script? I used the boilerplate code as a template so am pretty sure that nashorn:mozilla_compat.js is the right thing to use. Edit: Here is some input json you should be able to use to reproduce. [ { "entity": { "forecasts": [ { "validFrom": "2021-03-01T00:00:00Z", "validUntil": "2021-03-01T00:00:00Z", "validPeriod": "PT0S", "airTemperatureInCelsius": 2.0 }, { "validFrom": "2021-02-28T23:00:00Z", "validUntil": "2021-03-01T00:00:00Z", "validPeriod": "PT1H", "precipitationAmountInMillimeter": 0.0, "netRadiationInJoulePerCentimeterSquare": -9.8 }, { "validFrom": "2021-02-28T21:00:00Z", "validUntil": "2021-03-01T00:00:00Z", "validPeriod": "PT3H", "averageWindSpeedInKnots": 5.1 }, { "validFrom": "2021-03-01T01:00:00Z", "validUntil": "2021-03-01T01:00:00Z", "validPeriod": "PT0S", "airTemperatureInCelsius": 1.7 }, { "validFrom": "2021-03-01T00:00:00Z", "validUntil": "2021-03-01T01:00:00Z", "validPeriod": "PT1H", "precipitationAmountInMillimeter": 0.0, "netRadiationInJoulePerCentimeterSquare": -7.1 } ] }, "original": { "start_date": "2021-03-01T00:00:00.000Z", "end_date": "2021-03-01T01:00:00.000Z" } } ]Solved4.4KViews0likes1Comment