Why does Mule DataWeave array map strip top level objects? - mule

I'm trying to understand the behaviour of DataWeave v1.0 when it comes to mapping objects in a root JSON array.
At this stage I just want to map each item in the array as-is without mapping each individual field of the item. I need to do it for each item in the array because later on I want to edit some of the fields, but since there are potentially many I don't want the overhead of mapping them one-by-one.
This is my dataweave:
%dw 1.0
%output application/json
---
payload map {
($)
}
This is my input:
[
{
"MyString": "ABCD",
"MyNumber": 123,
"AnObject": {
"MyBool": false,
"MyNestedObject": {
"MyNestedString": "DEF"
}
}
}
]
I want my output to be (at this stage) exactly the same as my input.
Instead my (wrong) output is:
[
{
"MyString": "ABCD",
"MyNumber": 123,
"MyBool": false,
"MyNestedObject": {
"MyNestedString": "DEF"
}
}
]
As you can see the object AnObject is missing, although its children remain.
Things are worse if the input includes arrays, for example the input:
[
{
"MyString": "ABCD",
"MyNumber": 123,
"AnObject": {
"MyBool": false,
"MyNestedObject": {
"MyNestedString": "DEF"
}
},
"AnArray": [
{
"Title": "An array item",
"Description": "Pretty standard"
}
]
}
]
Throws the error:
Cannot coerce a :array to a :object.
I have played around with the mapObject operation on the root array items too, but I always run into the same behaviour. Is anyone able to explain what is happening here, and show me how I can copy each item in the root payload across dynamically.
Mule runtime is 3.9.1.

To go through each item in the array and let them as it is, you should do payload map $, that is the same as payload map ((item) -> item)
What you were doing is the same as: payload map ((item) -> {(item)}).
Here what you are returning for each item is the expression {(expr)} that in the DW version that runs on Mule 3.9.1, it has an accidental behavior where the expression tries to coerce expr (that in this case is an object) to array of objects and then it will try to flatten all the objects in that coerced array inside the parent object. It looks like is trying to coerce the value of the keys too, that's why DW throws the error.
This behavior of {()} changes in newer versions of DW.

Related

WSO2 Data Service query error : A JSON Array cannot be contained in the result records

I got this error when i was trying to invoke an sql query through a DataService .
The studenttest-1.0.0.dbs service, which is not valid, caused {1} DS Fault Message: A JSON Array cannot be contained in the result records
DS Code: UNKNOWN_ERROR
This is the Object to be returned from the DataService
<sql>SELECT * from etudiant where nom =?</sql>
<param name="nom" sqlType="STRING" />
<result outputType="json">
{
"Envelope": {
"Body": {
"GetFacturesClientResponse": {
"GetFacturesClientResult": {
"code": 0,
"nbreFactures": 2,
"totalResteAPayerFactures": 67.832,
"listeFactures": {
"Facture": [
{
"id":"$id",
"nom":"$nom",
"prenom":"$prenom",
"age":"$age",
"note":"$note"
}
]
},
"codeClient": "P-2008-043681",
"nom": "Oussama",
"prenom": "Haythem"
}
}
}
}
}
</result>
</query>```
You can't add complex JSON structures to the result mapping, you need to adhere to the following format. Read more here.
Also, the structure of the JSON template should follow some guidelines
in order to be compatible with the result. These guidelines are:
The top most item should be a JSON object. It cannot be a JSON array.
For handling multiple records from the result set, the immediate child
of the top most object can be a JSON array, and the array should
contain only a single object.
If only a single result is returned, the
immediate child of the top most object can be a single JSON object.
After the immediate child of the top most object, there cannot be
other JSON arrays in the mapping.
Hence try a simple mapping like below and add the rest of the JSON in the integration layer. (Interface the Dataservice with another API and modify the JSON structure within the API before responding to the client)
{
"listeFactures": {
"Facture": [
{
"id":"$id",
"nom":"$nom",
"prenom":"$prenom",
"age":"$age",
"note":"$note"
}
]
}
}

Kafka Lenses SQL - How to WHERE filter based on objects nested in an array

I am working in Kafka Lenses v2.2.2. I need to filter based on a the value of an object inside an array.
Sample message (redacted for simplicity):
{
"payload": {
"Data": {
"something" : "stuff"
},
"foo": {
"bar": [
{
"id": "8177BE12-F69B-4A51-B12E-976D2AE37487",
"info": "more_data"
},
{
"id": "06A846C5-2138-4107-A5B0-A2FC21B9F32D",
"info": "more_data"
}
]
}
}
In lenses this actually appears as a nested object with a integer properties... 0, 1, etc.
So I've tried this, but it is throwing an error: .0 appears out of place
SELECT *
FROM topic_name
WHERE payload.foo.bar.0.id = "8177BE12-F69B-4A51-B12E-976D2AE37487"
LIMIT 10
I tried wrapping the 0 in double/single quotes as well and that throws a 500 error.
I copied and pasted the UUID from the first message in the topic, so it's definitely there. I also copy and pasted the labels to rule out typos. I am thinking there is some special way to access arrays with nested objects like this, but I'm struggling to find any documentation or videos discussing it.
I can be confident the value is stored in the first array element, but methods that can search all objects would be awesome as well.
The syntax (if you know the array index - as in my initial question) is:
SELECT *
FROM topic_name
WHERE payload.foo.bar[0].id = "8177BE12-F69B-4A51-B12E-976D2AE37487"
LIMIT 10
Though I am still struggling to do this if the array index is unknown and you need to check them all. I'm assuming at this point it's not possible without a series of OR statements in the WHERE clause that checks them all.

VB.NET Processing Json from GitLab

I'm using the API of GitLab in VB.Net.
To request groups, I'm using GET /groups.
GitLab returns a JSON string like this:
[
{
"id":5,
"web_url":"https://XXXXX/groups/AAAA",
"name":"AAAA",
"path":"AAAA",
"description":"blabla",
"visibility":"private",
"share_with_group_lock":false,
"require_two_factor_authentication":false,
"two_factor_grace_period":48,
"project_creation_level":"developer",
},
{
"id":8,
"web_url":"https://XXXXX/groups/BBBBBB",
"name":"BBBBBB",
"path":"BBBBBB",
"description":"",
"visibility":"private",
"share_with_group_lock":false,
"require_two_factor_authentication":false,
"two_factor_grace_period":48,
"parent_id":null,
"ldap_cn":null,
"ldap_access":null
},
etc ...
]
It's quite complicated to parse it with Newtonsoft.Json so I would like first to convert it to an array of Dictionary.
Then, I will be able to loop through the array and get myrow("id") for instance.
I couldn't find how to do this, could you help me please?
String (list of Dictionary) -> List (Dictionary)

Using Junit assert on json array of elements fails on first element

I'm trying to use Katalon Studio for some webservice automation. I have been following this guide on how to parse returned Json body using jsonslurper.
https://docs.katalon.com/katalon-studio/tutorials/parse_json_responses.html
Everything is working fine as described in the guide. I wanted to see if I can use junit asserts, specifically the assertEquals() for better error text.
Given we have this
import groovy.json.JsonSlurper
String jsonString = {"menu": {
"id": "file",
"tools": {
"actions": [
{"id": "new", "title": "New File"},
{"id": "open", "title": "Open File"},
{"id": "close", "title": "Close File"}
],
"errors": []
}}}
JsonSlurper slurper = new JsonSlurper()
Map parsedJson = slurper.parseText(jsonString)
def array1 = parsedJson.menu.tools.actions
String onlickValue1 = ""
for(def member : array1) {
assertEquals("Open File", member.title)
break
}
What I'm having trouble with, is that my assert will thrown an error when comparing the very first title element it encounters (which is "New File").
What I intend is to loop through all the elements in the array and assert my expected value against all of them. If my expected value doesn't exist, then I'd fail.
I feel like I'm missing something, because we've done something similar in the past with java, but I just can't see it here.
So I figured out the problem was my inexperience/ignorance. When looking for solutions online I failed to understand with absolute certainty what the code I'm trying to implement is doing. I was using a for.each loop to assert elements in the array against my expected value. Which of course was failing, correctly, for every element that didn't match my expected value. So I made it work by adding an if statement as below:
String expectedValue = ''
for(def member : array1) {
if (member.title=="Open File")
{
expectedValue = member.title
}
break
}
assertEquals("Open File", member.title)
Also a simpler way I discovered is to use assertJ in the following way
assertThat(member).contains("Open File")
I understand there are better solutions to achieve what I'm trying to do. But for purposes of this question I considered it solved.

how to get dictionary same order as same i am getting from json in objective c

i am parsing json and what i get set of dictionary but after parsing it will automatically change it order. i just need same order as same i am getting from json parsing.
NOTE: i want to make one functionality which depends on dictionary order, i don't want to make it manually. so it will not need to make it every-time to do.it will help to change dynamically in future
Example:
From Json:
Section:
{
category:{},
location:{},
vehicle_type:{},
mode_type:{}
}
after convert into NSDicationary:
Section:
{
vehicle_type:{}
category:{},
location:{},
mode_type:{}
}
Thanks
Order of key:value doesn't matter for JSON, as you can directly access value with the help of key string. An dictionary does not support indexing of elements, so you can't.
Dictionaries are not ordered collections. On other hand, arrays are.
Note, if you don't have access over the json format, you got no guarantees about the order of elements, if you don't have hardcoded logic in your app.
Having said that, let's take a deeper look into your case. It happens that you have one main object in your json that is Section. What is more, you have 4 ordered properties of this object that are of specific kind of their own: 0: category; 1: location; 2: vehicle_type; 3: mode_type. So here comes the good part: just change your json to look something like this:
Section:
[
{
title: "category",
value: {}
},
{
title: "location",
value: {}
},
{
title: "vehicle_type",
value: {}
},
{
title: "mode_type",
value: {}
}
]
Having this json, you just go through the Section ordered elements, check the title of the element, and create the corresponding Object. This way you can achieve what you are after.