How can I create a HashMap in DataWeave2 inside a transformation in Mule 4? - hashmap

I need to make a HashMap inside a transform Message in Mule 4 to send to a service.
I was trying to make something like this:
%dw 2.0
import HasMap from java!java::util::HashMap
output application/java
---
HasMap ( <'data': write(payload, "application/json")>,
<'attribute1': 'att1'>,
<'attribute2': 'att2'>,
<'attribute3': 'att3'> )  
 
 
 
 
because as I successfully created a string using java libraries, I think that I can do the same for HashMap, but it is still not working:
%dw 2.0
import valueOf from java!java::lang::String
output application/java
---
valueOf({
data: write(payload, "application/json"),
atrribute1: 'att1',
atrribute2: 'att2',
atrribute3: 'att3'   }) 
At the beginning, I tried just to map like this:
%dw 2.0
output application/java
---
{
"data": write(payload, "application/json"),
"attribute1": "att1",
"attribute2": "att2",
"attribute3": "att3"
}
but the problem is that the service received something like this:
'\xac\xed\x00\x05sr\x00\x17java.util.LinkedHashMap4\xc0N\\x10l\xc0\xfb\x02\x00\x01Z\x00\x0baccessOrderxr\x00\x11java.util.HashMap\x05\x07\xda\xc1\xc3\x16`\xd1\x03\x00\x02F\x00\nloadFI\x00\tthresholdxp?#\x00\x00\x00\x00\x00\x0cw\x08\x00\x00\x00\x10\x00\x00\x00\x06t\x00\x04datat\x06\x19{\n "data": "{}", "attribute1": "att1",.....'
Any ideas of how can I create a normal Hash Map?
I expect to receive:
'data': '{....}', 'attribute1': 'att1','attribute2': 'att2', 'attribute3': 'att3'

So if you want the output to be a "java.util.HashMap" instance then you need to use
%dw 2.0
output application/java
---
{
"data": write(payload, "application/json"),
"attribute1": "att1",
"attribute2": "att2",
"attribute3": "att3"
} as Object {class : "java.util.HashMap"}
Though I don't think this is what you really want as HashMap is not something you want to try to a service, most probable you want all to be a json and that is being done by using output application/json

Related

ServiceStack ORMLite JSON Deserialization multiple levels

I've got a class containing a Dictionary like this:
Dictionary<string,object> Data
I put data on multiple levels into here, such as:
Data.Add("simple",4);
Data.Add("object",new Dictionary<string,object>{{"key",4}});
Data.Add("array",new List<string>{"a","b","c"});
Then I .Save() it with OrmLite, which is setup to use JSON instead of JSV:
SqliteDialect.Provider.StringSerializer = new JsonStringSerializer();
Looking inside the stored data, using SQL, it looks like perfectly valid JSON.
{
"simple": 4,
"object": {
"key": 4
},
"array": [
"a","b","c"
]
}
However, when I Load() the data back, it doesn't deserialize back to the original.
Here's a link to Gist Cafe, showing the problem:
https://gist.cafe/9ed2bbb3a6a0348f129c493887ae8170
By default JsonStringSerializer uses ServiceStack.Text Typed JSON Serializer which can't deserialize an object back to its original type since that type information is lost, all it sees is the runtime object Type which it leaves as a string since it doesn't know what other object it should deserialize to.
Which is why it's recommended that you serialize typed DTOs so the type information is preserved, e.g:
class CustomData
{
public int Simple { get; set; }
public Dictionary<string,int> Object { get; set; }
}
If you want to deserialize anonymous object data structures into untyped collections you can configure ServiceStack.Text to use JS Utils to handle deserializing arbitrary JSON into untyped data structures by registering it with:
ServiceStack.JS.Configure();
Which I've done in this modified gist:
https://gist.cafe/953f2da51a5077ecf7b5109c14ec2c32
Which outputs the expected result:
{
Id: 1,
Data:
{
simple: 4,
object:
{
key: 4
},
array:
[
a,
b,
c
]
}
}
Whilst it works in this instance because you're using only serializing JSON data types, it wont work if your object dictionary contains complex types because all JS Utils can see is the raw JSON string without any type information, so it's only able to deserialize into untyped collections that matches the JSON object - which is why it's recommended to serialize Typed DTOs so the types are preserved.

TF Keras Model Serving REST API JSON Input Format

So I tried following this guide and deploy the model using docker tensorflow serving image. Let's say there are 4 features: feat1, feat2, feat3 and feat4. I tried to hit the prediction endpoint {url}/predict with this JSON body:
{
"instances":
[
{
"feat1": 26,
"feat2": 16,
"feat3": 20.2,
"feat4": 48.8
}
]}
I got 400 response code:
{
"error": "Failed to process element: 0 key: feat1 of 'instances' list. Error: Invalid argument: JSON object: does not have named input: feat"
}
This is the signature passed to model.save():
signatures = {
'serving_default':
_get_serve_tf_examples_fn(model,
tf_transform_output).get_concrete_function(
tf.TensorSpec(
shape=[None],
dtype=tf.string,
name='examples')),
}
I understand that from this signature that in every instances element, the only field being accepted is "examples" but when I tried to only pass this one only with empty string:
{
"instances":
[
{
"examples": ""
}
]
}
I also got bad request: {"error": "Name: <unknown>, Feature: feat1 (data type: int64) is required but could not be found.\n\t [[{{node ParseExample/ParseExampleV2}}]]"}
I couldn't find in the guide how to build the JSON body request the right way, it would be really helpful if anyone can point this out or give references regarding this matter.
In that example, the serving function expects a serialized tf.train.Example proto as input. This page explains how binary data can be passed to a deployed model as a string (explaining why the signature expects a tensor of strings). So what you need to do is build an Example proto containing your features and send that over. It could look something like this:
import base64
import tensorflow was tf
features = {'feat1': 26,, 'feat2': 16, "feat3": 20.2, "feat4": 48.8}
# Create an Example proto from your feature dict.
feature_spec = {
k: tf.train.Feature(float_list=tf.train.FloatList(value=[float(v)]))
for k, v in features.items()
}
example = tf.train.Example(
features=tf.train.Features(feature=feature_spec)).SerializeToString()
# Encode your serialized Example using base64 so it can be added into your
# JSON payload.
b64_example = base64.b64encode(example).decode()
result = [{'examples': {'b64': b64_example}}]
What is the output of saved_model_cli show --dir /path/to/model --all? You should follow the output to serialize your request.
I tried to solve this problem by changing the signature serving input but it raised another exception. This problem already solved, check it out here.

Scenario Outline to use different data set by passing in REST API JSON body object

We have REST APIs with JSON BODY arrays/objects. To control the data to go in the JSON file at Runtime, using testdata.properties file where defining the data and calling that as below. We are using cucumber Serenity.
Testdata.properties file:
Value = 123
StepDefinition file:
#Given("^Set the \"([^\"]*)\" with \"([^\"]*)\"$")
public void set_data_parameterization (String fieldName, String Value) {
if (fieldName.contains("Test")) {
jsonObjectNew.getAsJsonObject("TestInfo").add("Value",
gson.toJsonTree(Value));
}
System.err.println("Test value fetched from the Scenario outline");
}
JSON File:
{
"TestInfo": {
"Test123": 3,
"Value": 50 // this value to be replaced
}
}
.feature file:
Scenario Outline::
1. Testing data parameterize
Given Set the URL for "Test" as "base"
And Set the "Test" with "Value"
Examples:
|Value|
|700|
|710|
If calling the variable data from .properties file works fine, however if want to have different sets of data to be executed for the same scenario. How can it be achieved. Tried with Examples in feature file, but when run the file as cucumbertest>getting the actual payload value which is 50. It is not replacing with 700/710.
Please guide.
Able to get values as expected now, the issue was I was trying as "String" (ex: "Values"). When tried as in .feature file and rest of the code is similar.
Able to get values iterated of given Examples.

JAX-RS 2 and Jersey 2 : how to pass an (hash)map on a GET request

I simply want to pass an map to my #GET method on my web services using JAX-RS 2. I want to know if it's possible and how to make it, even if GET's methods don't have any body.
Like this :
#GET
#Path(??)
#Produces({"application/xml", "application/json"})
public User find(#PathParam(??) HashMap<String, String> map) {
// work on map !
}
I've seen that it existed the MultiValued map but it's for the parameters. How to pass an map please ?
Thanks by advance !
You will need to have Jackson jars in your classpath (or any other XML / JSON to Map mapper)
You probably don't want to pass the map on the #PathParam, for aesthetical, convention and security reasons. You usually pass a JSON / XML object as the request body, e.g. using a POST / PUT
#POST
#Path("/anypath")
#Consumes({"text/xml", "application/json"})
public User find(HashMap<String, String> map) {
//magic should happen
}
Then just pass a POST / PUT request with content type application/json or text/xml that has
e.g.
{
"key1": "value1"
"key2": "value2"
}
If you have the right Jackson / Moxy etc mapper in the classpath, it will do the conversion between the JSON / XML format to a java.util.Map (or even a POJO) for you
The #Produces is only needed if you intend to also return XML / JSON, but since you are expecting either XML or JSON, then having a #Consumes makes sense here.
However, if you must pass the JSON object on a GET request, e.g. as a request param, take a look at this question: Convert JSON query parameters to objects with JAX-RS
p.s. for xml the mime is text/xml and not application/xml
Get comfortable with #Context.
#GET
public Response superSpecialSearch(#Context UriInfo info, #Context HttpHeaders headers, #Context SecurityContext securityContext) {
var iAmAMutivalueMap = info.getQueryParameters(true);
var searchResults = searchForThings( iAmAMultivalueMap );
return Response.ok(searchResults )
}

AngularJS - How to send multidimensional $http.get() data

So I have a JSON array that looks something like this:
var myData = {
foo : {
biz : 'baz',
fig : 'tree'
}
}
This could be typed into the address bar like:
http://www.mysite.com/index?foo[biz]=baz&foo[fig]=tree
And this will work as expected.
The problem is that when I supply this myData object to AngularJS's $http service like:
$http.get('http://www.mysite.com', {
data : myData
});
It escapes the query string and doesn't appear to even be the right format even if it weren't esaped in the weird way it is. It looks something like:
url?foo=%7B%22biz%22%3A%22baz%22%2C%22fig%22%3A%22tree%22%7D
How can I make this work?
This is actually in the right format. Assuming your back-end is PHP, when you do $_GET['foo'] you will get %7B%22biz%22%3A%22baz%22%2C%22fig%22%3A%22tree%22%7D. The strange characters you see are because Angular is url encoding the string for you. This has to be done before transmitting the data. If you type it out as foo[biz]=baz&foo[fig]=tree in your browser, the browser usually urlencodes it automatically.
After urldecoding and json_decoding this, you will get the data you expect.
$foo = json_decode(urldecode($input), true);
Array
(
[biz] => baz
[fig] => tree
)
You can then access these as $foo['biz'] and $foo['fig']
Demo

Resources