My input is an Array of Java Objects:
[{"name"="Demo","platform"=[{"id"="1","value"="ios"},{"id"="2","value"="android"}],"language"=[{"id"="1","value"="eng"}],"date"="20/05/2018"}, {"name"="Kernel","platform"=[{"id"="1","value"="macos"},{"id"="2","value"="linux"}],"language"=[{"id"="1","value"="ger"}],"date"="20/05/2018"}]
Each Java Object contains arrays in Platform and language key like this example:
{"name"="Demo","platform"=[{"id"="1","value"="ios"},{"id"="2","value"="android"}],"language"=[{"id"="1","value"="eng"}],"date"="20/05/2018"}
This is the output expected in text/plain type:
{"name":"Demo","platform":[{"id":"1","value":"ios"},{"id":"2","value":"android"}],"language":[{"id":"1","value":"eng"}],"date":"20/05/2018"}
{"name":"Kernel","platform":[{"id":"1","value":"macos"},{"id":"2","value":"linux"}],"language":[{"id":"1","value":"ger"}],"date":"20/05/2018"}
Each object from Java to JSON
Indent=false per line
No brackets or commas between objects. Each object per line
Must not affect Platform and Language key arrays
Is it possible to apply this without having to play with String replace?
So you can use the write function to transform each element to application/json and with the writer property indent=false
%dw 2.0
output text/plain
---
payload map ((item, index) -> write(item, "application/json", {indent: false})) reduce ((item, accumulator) -> item ++ "\n" ++ accumulator)
Or if you use mule 4.2 you can directly use application/x-ndjson and it should work directly
%dw 2.0
output application/x-ndjson
---
payload
Related
I want to reduce or replace this [] with {}
input: ["abcd,"whyf","thsr"]
output: {"abcd,"whyf","thsr"}
Assuming the input is in JSON it means it is an array. It could be just a string too. The output is not a valid JSON document, because starting with a curly brackets it means it should be an object, but it misses keys for each value.
If for some reason you are intending to just output a string with the square brackets replaced with the curly brackets, then you can transform the input as a string and then use string replaces to change the characters, but be aware that the output is not valid JSON, nor any other supported structured format.
%dw 2.0
output application/java
---
write(payload,"application/json",{indent:false}) replace /\[/ with("{") replace /]/ with("}")
Output (as a string):
{"abcd","whyf","thsr"}
Assuming the output to be string you can also try the following which uses joinBy
%dw 2.0
output text/plain
---
'{"' ++ (payload joinBy '","') ++ '"}'
Description:
Input should be json object.
Sort the key, value pairs alphabetically on basis of key.
Generate the output as mentioned in the example below.
Example:
Input:
{
"name":"<<your_name>>",
"age":"<<your_age>>",
"city":"<<your_city>>",
"role":"<<your_role>>"
}
Output:
age=<<your_age>>&city=<<your_city>>&name=<<your_name>>&<<your_role>>
Note: Please send the input using postman and your code should work for any number of key, value pairs.
First let me say that if you intend to use the as the query parameters string of an HTTP request it is not a good idea. It would make a lot more sense to use the HTTP Requester to just send each attribute with the requester as a query parameter. It will automatically apply URL encoding and handle the parameters.
Example:
<set-variable value='#[{
name:"<<your_name>>",
age:"<<your_age>>",
city:"<<your_city>>",
role:"<<your_role>>"
}]' doc:name="Set Variable" variableName="person"/>
<http:request method="GET" config-ref="HTTP_Request_configuration" path="/backend" >
<http:query-params><![CDATA[#[vars.person]]]></http:query-params>
</http:request>
See how you just tell it to use the object to generate the query parameters. The output request will be:
GET /backend?name=%3C%3Cyour_name%3E%3E&age=%3C%3Cyour_age%3E%3E&city=%3C%3Cyour_city%3E%3E&role=%3C%3Cyour_role%3E%3E HTTP/1.1
If you absolutely feel that you have to build the query parameters string manually see below.
Example:
%dw 2.0
output application/json
import * from dw::core::URL
---
// it is not recommended to use this, use the HTTP Requester <http:query-params> instead
encodeURI(
payload pluck ((value, key, index) ->
{ key: key, value: value}
)
orderBy( $.key )
reduce ((val, acc = "") ->
acc ++ (if(sizeOf(acc) !=0) "&" else "") ++ val.key ++ "=" ++ val.value)
)
I am posting the following object
{
skillName : "Professional Skills"
_id : {$oid: "5adf23946ab671bf6cb36aff"}
}
to the DjangoService given below:
#csrf_exempt
#api_view(['GET','POST'])
def saveSubjectView(request): #this service will add & update Subject
if request.method == 'POST':
try:
stream = StringIO(request.body)
subject = JSONParser().parse(stream)
print("The subejct is ")
pp.pprint(subject)
serializedsubject = json.loads(json_util.dumps(subject))
print("serializedsubject")
pp.pprint(serializedsubject)
The output that I am getting is
'skillType': { u'_id': { }, u'skillName': u'Professional Skills'}
The ObjectId posted from the front end (AngularJS) is not printed in the service. I know that I can fix it by removing the $oid while posting from the AngularJS application. But I would like to know why this is not happening. I have searched the documents and I couldn't get a proper reply. May be the keywords I used are wrong. Keywords used are : "JSON serialisation of ObjectId", "$oid json serialization using Django".
The complete object I am posting to the Django service is given below:
Exactly. $oid or anything prefixed with $ is an internal format and reserved, so you cannot post field names. The convention is from MongoDB Extended JSON where such prefixes are used to identify the BSON Type for proper conversion, and used as a serializable transport since these "types" are not supported in basic JSON.
So the solution is to actually use the bson.json_util to "deserialize" the JSON string right from the start:
from bson import json_util
# serializedsubject = json.loads(json_util.dumps(subject))
serializedsubject = json_util.loads(request.body) # correct usage
Or more succinctly self contained:
input = '{ "skillName" : "Professional Skills" ,"_id" : { "$oid": "5adf23946ab671bf6cb36aff"} }'
json_util.loads(input)
Returns
{u'skillName': u'Professional Skills', u'_id': ObjectId('5adf23946ab671bf6cb36aff')}
This correctly casts objects from any keys notated with the Extended JSON Syntax to their correct BSON Type, as also supported in the driver functions. And naturally the driver will then convert back to BSON when sending to MongoDB.
If for some reason your request.body contains anything other than a "string" which is valid for input to the function, then it is up to your code to convert it to that point. But there should be no need to "parse to JSON" and then "stringify" again just to input to the function.
NOTE: If you have not already done so within your JavaScript client side of the application, there is also the bson package available. This would allow where such Extended JSON is "received" from the server the translation into the BSON Types as JavaScript Objects, and of course then the serialization of such objects back into the Extended JSON Format.
This would in fact be recommended where "type" information needs to be maintained with the data transmitted and kept between client and server.
I want to send an array of objects trough a fetch call in react native in x-www-form-urlencoded format
global.modifiedOffline.forEach((elem)=>{
data["array[]"] = elem;
});
alert(data);
const formBody = Object.keys(data).map(key => encodeURIComponent(key) +
'=' + encodeURIComponent(data[key])).join('&');
This is what i've been trying to do but in the back end server i get a list of:
['[object Object]' ... ] which i cannot parse or use.
Currently, you are encoding objects. When you try to do that, encodeURIComponent tries to get a string representation of the object you supply it and [Object object] is the string representation in JS.
In order to be able to encode it, first you need to get it into a proper string format such as JSON as suggested by #Val. However, this part depends on the server side implementation you have. encodeURIComponent will only transform your string into URI component by replacing characters such as space with their escape counterparts (for example, %20).
In JMeter I want to check the number of objects in a JSON array, which I receive from the server.
For example, on a certain request I expect an array with 5 objects.
[{...},{...},{...},{...},{...}]
After reading this: count members with jsonpath?, I tried using the following JSON Path Assertion:
JSON Path: $
Expected value: hasSize(5)
Validate against expected value = checked
However, this doesn't seem to work properly. When I actually do receive 5 objects in the array, the response assertion says it doesn't match.
What am I doing wrong?
Or how else can I do this?
Although JSONPath Extractor doesn't provide hasSize function it still can be done.
Given the example JSON from the answer by PMD UBIK-INGENIERIE, you can get matches number on book array in at least 2 ways:
1. Easiest (but fragile) way - using Regular Expression Extractor.
As you can see, there are 4 entries for category like:
{ "category": "reference",
{ \"category\": \"fiction\"
...
If you add a Regular Expression Extractor configured as follows:
It'll capture all the category entries and return matches number as below:
So you will be able to use this ${matches_matchNr} variable wherever required.
This approach is straightforward and easy to implement but it's very vulnerable to any changes in the response format. If you expect that JSON data may change in the foreseeable future continue with the next option.
2. Harder (but more stable) way - calling JsonPath methods from Beanshell PostProcessor
JMeter has a Beanshell scripting extension mechanism which has access to all variables/properties in scope as well as to the underlying JMeter and 3rd-party dependencies APIs. In this case you can call JsonPath library (which is under the hood of JsonPath Extractor) directly from Beanshell PostProcessor.
import com.jayway.jsonpath.Criteria;
import com.jayway.jsonpath.Filter;
import com.jayway.jsonpath.JsonPath;
Object json = new String(data);
List categories = new ArrayList();
categories.add("fiction");
categories.add("reference");
Filter filter = Filter.filter(Criteria.where("category").in(categories));
List books = JsonPath.read(json, "$.store.book[?]", new Filter[] {filter});
vars.put("JSON_ARRAY_SIZE", String.valueOf(books.size()));
The code above evaluates JSONPath expression of $.store.book[?] against parent sampler response, counts matches number and stores it into ${JSON_ARRAY_SIZE} JMeter Variable
which can later be reused in an if clause or an assertion.
References:
JMeter – Working with JSON – Extract JSON response
JMeter's User Manual Regular Expressions entry
JSON Path Documentation and Examples
How to use BeanShell: JMeter's favorite built-in component
This is not possible with the plugin you are using (JMeter-plugins).
But it can be done with JSON Extractor since JMeter 3.0, this plugin has been donated by UbikLoadPack (http://jmeter.apache.org/changes_history.html)
Example:
Say you have this JSON that contains an array of books:
{ "store": {"book": [
{ "category": "reference","author": "Nigel Rees","title": "Sayings of the Century","price": 8.95},
{ "category": "fiction","author": "Evelyn Waugh","title": "Sword of Honour","price": 12.99},
{ "category": "fiction","author": "Herman Melville","title": "Moby Dick","isbn": "0-553-21311-3","price": 8.99},
{ "category": "fiction","author": "J. R. R. Tolkien","title": "The Lord of the Rings","isbn": "0-395-19395-8","price": 22.99}
],
"bicycle": {"color": "red","price": 19.95}} }
To have this count:
1/ Add JSON Extractor:
The count will be then available bookTitle_matchNr which you can access through:
${bookTitle_matchNr}
Running this Test Plan would display this:
As you can see, Debug Sampler-${bookTitle_matchNr} shows Debug Sampler-4