Groovy JSONArray : org.json.JSONException: when decoding string with \" - groovy

I get no way to parse this Json which seems to be valid for me :
def diffOfApi='''[{"op":"replace","path":"/data/0/messageBody","value":"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<WCS reference=\"336042800000431486\"><PREPARATION_REQUEST requestId=\"WDP_PICKVRAC3\" date=\"2022-02-08 18:33:39\"><CONTAINERS><CONTAINER containerId=\"336042800000431486_21_21121\" handle=\"CREATE\" wmsOrderId=\"WDP_PICKVRAC3\" site=\"CPEEPF\" status=\"CREATED\" referenceDate=\"2022-02-08 18:33:39\" purgeAuthorized=\"false\"><BARCODES><BARCODE main=\"false\" reusable=\"false\">336042800000431486</BARCODE></BARCODES><PACKAGING>TX</PACKAGING><WEIGHT_CHECKING mode=\"NO\"/></CONTAINER></CONTAINERS></PREPARATION_REQUEST></WCS>"}]'''
JSONArray jsonArray = new JSONArray(diffOfApi);
I get this error :
Reason:
org.json.JSONException: Expected a ',' or '}' at 71 [character 72 line 1]
at org.json.JSONTokener.syntaxError(JSONTokener.java:433)
at org.json.JSONObject.<init>(JSONObject.java:229)
at org.json.JSONTokener.nextValue(JSONTokener.java:363)
at org.json.JSONArray.<init>(JSONArray.java:115)
at org.json.JSONArray.<init>(JSONArray.java:144)
at TEST.run(TEST:32)
at com.kms.katalon.core.main.ScriptEngine.run(ScriptEngine.java:194)
at com.kms.katalon.core.main.ScriptEngine.runScriptAsRawText(ScriptEngine.java:119)
at com.kms.katalon.core.main.TestCaseExecutor.runScript(TestCaseExecutor.java:442)
at com.kms.katalon.core.main.TestCaseExecutor.doExecute(TestCaseExecutor.java:433)
at com.kms.katalon.core.main.TestCaseExecutor.processExecutionPhase(TestCaseExecutor.java:412)
at com.kms.katalon.core.main.TestCaseExecutor.accessMainPhase(TestCaseExecutor.java:404)
at com.kms.katalon.core.main.TestCaseExecutor.execute(TestCaseExecutor.java:281)
at com.kms.katalon.core.main.TestCaseMain.runTestCase(TestCaseMain.java:142)
at com.kms.katalon.core.main.TestCaseMain.runTestCase(TestCaseMain.java:133)
at com.kms.katalon.core.main.TestCaseMain$runTestCase$0.call(Unknown Source)
at TempTestCase1644483473725.run(TempTestCase1644483473725.groovy:25)
I think it is due to " encapsulated xml in item value
Any idea to make it working ?

You can replace the \" characters with ' to allow for JSON- and later XML-processing:
import groovy.json.*
import groovy.json.*
def diffOfApi='''[{"op":"replace","path":"/data/0/messageBody","value":"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<WCS reference=\"336042800000431486\"><PREPARATION_REQUEST requestId=\"WDP_PICKVRAC3\" date=\"2022-02-08 18:33:39\"><CONTAINERS><CONTAINER containerId=\"336042800000431486_21_21121\" handle=\"CREATE\" wmsOrderId=\"WDP_PICKVRAC3\" site=\"CPEEPF\" status=\"CREATED\" referenceDate=\"2022-02-08 18:33:39\" purgeAuthorized=\"false\"><BARCODES><BARCODE main=\"false\" reusable=\"false\">336042800000431486</BARCODE></BARCODES><PACKAGING>TX</PACKAGING><WEIGHT_CHECKING mode=\"NO\"/></CONTAINER></CONTAINERS></PREPARATION_REQUEST></WCS>"}]'''
diffOfApi = diffOfApi.replaceAll( /=.{1}([^"]+)"/, "='\$1'" )
def jsonArray = new JsonSlurper().parseText diffOfApi
assert 3 == jsonArray.first().size()
def xml = new XmlSlurper().parseText jsonArray.first().value // root element points to <WCS/>
assert 'WDP_PICKVRAC3' == xml.PREPARATION_REQUEST.#requestId.text()

you have incorrectly encoded json string.
if json contains doublequote in a value " - it must be encoded as \" but inside the groovy/java code each \ also must be encoded with \\
so when you have following in code:
def x = '''{"x":"abc\"def"}'''
then actual x value at runtime would be
{"x":"abc"def"}
that is incorrect json
so, x should be defined as
def x = '''{"x":"abc\\"def"}'''
to have runtime value
{"x":"abc\"def"}

Related

why in the raw data the first byte is in asciii

I've got the followings raw data in bytes :
b'\r\xdc\xc9\x00\x00\x00\x00\x00\x9f\x03\xdf\x00\x9f\x03\xdfI\x82W\x00\x00\x97\x00'
b'\x16\xd9\xc9\x00\x00\x00\x00\x00\x9f\x03\xdf\x00\x9f\x03\xdfI\xf2d\x02\x00\x97\x00'
b'K\xde\xc9\x01\x00\x00\x00\x00\x9f\x03\xdf\x00\x9f\x03\xdfI\x82W\x00\x00\x97\x00'
b':\xda\xc9\x02\x00\x00\x00\x00\x9f\x03\xdf\x00\x9f\x03\xdfI\x82W\x00\x00\x97\x00'
b'B\xda\xc9\x00\x00\x00\x00\x00\x9f\x03\xdf\x00\x9f\x03\xdfI\x82W\x00\x00\x97\x00'
b'\x15\xdb\xc9\x01\x00\x00\x00\x00\x9f\x03\xdf\x00\x9f\x03\xdfI\x82W\x00\x00\x97\x00'
As you can see the first value is in ascii. For example this couple are the same:
b'B\xda\xc9\x00\x00\x00\x00\x00\x9f\x03\xdf\x00\x9f\x03\xdfI\x82W\x00\x00\x97\x00'
Looking into the code of pyshark i see this :
def get_raw_packet(self):
assert "FRAME_RAW" in self, "Packet contains no raw data. In order to contains it, " \
"make sure that use_json and include_raw are set to True " \
"in the Capture object"
raw_packet = b''
byte_values = [''.join(x) for x in zip(self.frame_raw.value[0::2], self.frame_raw.value[1::2])]
for value in byte_values:
raw_packet += binascii.unhexlify(value)
return raw_packet
And my code is the following :
import pyshark
from pyshark.capture.pipe_capture import PipeCapture
import os
FIFO = 'informacion.pcap'
def print_callback(pkt):
print (pkt.get_raw_packet())
with open(FIFO) as fifo:
capture = PipeCapture(pipe=fifo,use_json=True,include_raw=True)
capture.apply_on_packets(print_callback)

Groovy & SoapUI - NumberFormatException

In SoapUI I am able to get a response from a web service that gives me a string return.
XML Node Value
soap:Envelope {Envelope}
soap:Body {Body}
EuroConvertorResponse
EuroConvertorResult 1.0966 {xsd:string}
I manage to read the response in Groovy script but I get number format exception. My code is:
String conversionString = context.expand(
'${EuroConvertorRequest#Response#declare namespace
ns1=\'http://tempuri.org/\'; //ns1:EuroConvertorResponse[1]}' )
double convertedRate = Double.parseDouble(conversionString);
The exact error I get is:
java.lang.NumberFormatException: For input string: " 1.0966 " error at line: 10.
If I hard code the response like below it works fine though!
String conversionRate = "1.0966";
double convertedRate = Double.parseDouble(conversionString);
Any idea?
You are using incorrect xpath, I believe. Supposed to query for EuroConvertorResult, not EuroConvertorResponse.
Try changing from:
String conversionString = context.expand('${EuroConvertorRequest#Response#declare namespace ns1=\'http://tempuri.org/\'; //ns1:EuroConvertorResponse[1]}' )
To:
String conversionString = context.expand('${EuroConvertorRequest#Response#declare namespace ns1=\'http://tempuri.org/\'; //ns1:EuroConvertorResult}' )
Or in fact, get the double value in single line itself by coercing as below, by adding as Double at the end:
def conversionResult = context.expand('${EuroConvertorRequest#Response#declare namespace ns1=\'http://tempuri.org/\'; //ns1:EuroConvertorResult}' ) as Double
assert conversionResult instanceof Double
Alternatively, you can use XmlSlurper to achieve the same:
def result = new XmlSlurper().parseText(context.expand('${EuroConvertorRequest#Response}').'**'.find{it.name() == 'EuroConvertorResult'}.text() as Double
log.info result
assert result instanceof Double

Typecasting in Groovy

I am trying to parse an yaml file in Groovy. However I am facing issue while typecasting the result to Map object.
Here is my logic
import org.yaml.snakeyaml.Yaml
import java.util.Map
Reader reader = null
int tokenCount = 0
def Map map = null
StringTokenizer st = new java.util.StringTokenizer("Country.State.City", ".")
reader = new FileReader("filepath")
String val = null
Yaml yaml = new Yaml()
map = (Map) yaml.load(reader)
tokenCount = st.countTokens()
for (i=1; i < tokenCount; i++) {
String token = st.nextToken()
map = (Map) map.get(token)
}
val = map.get(st.nextToken()).toString()
However I am getting error at line:
map = (Map) map.get(token)
where it says:
"org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'some value' with class 'java.lang.String' to class 'java.util.Map' error at line: 15"..
Where I am going wrong?
your provided yaml file is syntactically incorrect. This is a fixed version:
location: C:\\Users\\amah11\\Desktop\\New folder
type: hi
Header:
Code:
Start: 0
End: 2
value: H00
Owner:
Start: 3
End: 5
value: AIM
User:
Start: 6
End: 8
Value: AIM
number: 1
Note that Code: **Static** in the original messes things up. And all the keys on the final level need a space after the : (e.g. Start:3 is wrong).
The actual error message is:
Caught: org.codehaus.groovy.runtime.typehandling.GroovyCastException: Cannot cast object 'Static Start:0 End:2 value:H00' with class 'java.lang.String' to class 'java.util.Map'
which is rather clear in showing, that there is something wrong with the original file.
You might want to consider using an editor, that detects errors like this right away.
An alternative to the original code, would be the use of inject on the tokenizer:
def map = new Yaml().load(new FileReader("cardconfig.yml"))
println new StringTokenizer('Header.Code.End', '.').inject(map) { r, s -> r.get(s) }
BTW: you don't need to import java.util in groovy.

groovy read a file, resolve variables in file content

I am new to Groovy and I could not get around this issue. I appreciate any help.
I want to read a file from Groovy. While I am reading the content, for each line I want to substitute the string '${random_id}' and '${entryAuthor}' with different string values.
protected def doPost(String url, URL bodyFile, Map headers = new HashMap() ) {
StringBuffer sb = new StringBuffer()
def randomId = getRandomId()
bodyFile.eachLine { line ->
sb.append( line.replace("\u0024\u007Brandom_id\u007D", randomId)
.replace("\u0024\u007BentryAuthor\u007D", entryAuthor) )
sb.append("\n")
}
return doPost(url, sb.toString())
}
But I got the following error:
groovy.lang.MissingPropertyException:
No such property: random_id for class: tests.SimplePostTest
Possible solutions: randomId
at foo.test.framework.FooTest.doPost_closure1(FooTest.groovy:85)
at groovy.lang.Closure.call(Closure.java:411)
at groovy.lang.Closure.call(Closure.java:427)
at foo.test.framework.FooTest.doPost(FooTest.groovy:83)
at foo.test.framework.FooTest.doPost(FooTest.groovy:80)
at tests.SimplePostTest.Post & check Entry ID(SimplePostTest.groovy:42)
Why would it complain about a property, when I am not doing anything? I also tried "\$\{random_id\}", which works in Java String.replace(), but not in Groovy.
You are doing it the hard way. Just evaluate your file's contents with Groovy's SimpleTemplateEngine.
import groovy.text.SimpleTemplateEngine
def text = 'Dear "$firstname $lastname",\nSo nice to meet you in <% print city %>.\nSee you in ${month},\n${signed}'
def binding = ["firstname":"Sam", "lastname":"Pullara", "city":"San Francisco", "month":"December", "signed":"Groovy-Dev"]
def engine = new SimpleTemplateEngine()
template = engine.createTemplate(text).make(binding)
def result = 'Dear "Sam Pullara",\nSo nice to meet you in San Francisco.\nSee you in December,\nGroovy-Dev'
assert result == template.toString()
you better use groovy.text.SimpleTemplateEngine class; check this for more details http://groovy.codehaus.org/Groovy+Templates
The issue here is that Groovy Strings will evaluate "${x}" by substituting the value of 'x', and we don't want that behaviour in this case. The trick is to use single-quotes which denote plain old Java Strings.
Using a data file like this:
${random_id} 1 ${entryAuthor}
${random_id} 2 ${entryAuthor}
${random_id} 3 ${entryAuthor}
Consider this code, which is analogous to the original:
// spoof HTTP POST body
def bodyFile = new File("body.txt").getText()
StringBuffer sb = new StringBuffer()
def randomId = "257" // TODO: use getRandomId()
def entryAuthor = "Bruce Eckel"
// use ' here because we don't want Groovy Strings, which would try to
// evaluate e.g. ${random_id}
String randomIdToken = '${random_id}'
String entryAuthorToken = '${entryAuthor}'
bodyFile.eachLine { def line ->
sb.append( line.replace(randomIdToken, randomId)
.replace(entryAuthorToken, entryAuthor) )
sb.append("\n")
}
println sb.toString()
The output is:
257 1 Bruce Eckel
257 2 Bruce Eckel
257 3 Bruce Eckel

how to fix expecting anything but ''\n''; got it anyway

I have the following line in my code
def genList = (args[]?.size() >=4)?args[3]: "
when I run my whole code I get the following error
expecting anything but ''\n''; got it anyway at line: 9, column: 113
here I am adding the whole code so you can see what I am doing
def copyAndReplaceText(source, dest, targetText, replaceText){
dest.write(source.text.replaceAll(targetText, replaceText))
}
def dire = new File(args[0])
def genList = (args[]?.size() >=4)?args[3]: " // check here if argument 4 is provided, and generate output if so
def outputList = ""
dire.eachFile {
if (it.isFile()) {
println it.canonicalPath
// TODO 1: copy source file to *.bak file
copy = { File src,File dest->
def input = src.newDataInputStream()
def output = dest.newDataOutputStream()
output << input
input.close()
output.close()
}
//File srcFile = new File(args[0])
//File destFile = new File(args[1])
//File srcFile = new File('/geretd/resume.txt')
//File destFile = new File('/geretd/resumebak.txt')
File srcFile = it
File destFile = newFile(srcFile + '~')
copy(srcFile,destFile)
// search and replace to temporary file named xxxx~, old text with new text. TODO 2: modify copyAndReplaceText to take 4 parameters.
if( copyAndReplaceText(it, it+"~", args[1], args[2]) ) {
// TODO 3: remove old file (it)
it.delete()
// TODO 4: rename temporary file (it+"~") to (it)
// If file was modified and parameter 4 was provided, add modified file name (it) to list
if (genList != null) {
// add modified name to list
outputList += it + "\n\r"
}
}
}
}
// TODO 5: if outputList is not empty (""), generate to required file (args[3])
if (outputList != ""){
def outPut = new File(genList)
outPut.write(outputList)
}
Thank you
Just close your double quotes
def genList = (args?.size() >=4)?args[3]: ""
The specific OP question was already answered, but for those who came across similar error messages in Groovy, like:
expecting anything but '\n'; got it anyway
expecting '"', found '\n'
It could be caused due to multi-line GString ${content} in the script, which should be quoted with triple quotes (single or double):
''' ${content} ''' or """ ${content} """
Why do you have a single " at the end of this line: def genList = (args[]?.size() >=4)?args[3]: "?
You need to make it: def genList = (args[]?.size() >=4)?args[3]: ""
You need to add a ; token at the end of def outputList = ""
Also get rid of the " at the end of def genList = (args[]?.size() >=4)?args[3]: "

Resources