Extract JSON inside JSON in CN1 - codenameone

My app receives JSON responses from an API. When it arrives, the app uses the JSONParser class to get a result as a Map:
JSONParser jp = new JSONParser();
Map <String, Object> result = jp.parseJSON(new InputStreamReader(input, "UTF-8"));
The "result" contains 2 values. First a URL that I can get using the key "url":
String url = result.get("url");
And second, another set of data which is in JSON format and I get using the key "eager". I tried to extract it to a Map:
java.util.List<Map<String, Object>> eager = (java.util.List<Map<String, Object>>) result.get("eager");
The resulting Map does not behave like a Map, so I passed the whole eager Map to a String, just to check the content and I noticed that the data is inside brackets, like this:
[{item1=x, item2=x,.....itemN=x}]
Question:
How can I get the data as a JSON object?

You parse your result String as a List. What happend if you try to get "data" like this ?
java.util.List<Map<String, Object>> newResult = (java.util.List<Map<String, Object>>) result.get(0);

You need to use the key "root" not "data" to get your list.

"result" is a Map.
"eager" is a List of Maps.
You need to get the first position of the eager Map in order to get the Map with the data:
Map <String, Object> result = jp.parseJSON(new InputStreamReader(input, "UTF-8"));
java.util.List<Map<String, Object>> eager = (java.util.List<Map<String, Object>>) result.get("eager");
Map<String, Object> eagerMap = (Map<String, Object>) eager.get(0);

Related

How to concatenate two maps in apex

I have two maps, different sObject fields are being stored, one for each sObject. I want to add the fields from map1 to the beginning of map2 or vise-versa.
Is it possible to add the contents of one map to another without merging similar fields or keys? Can the values in a map that is an array be placed in such a way that they come after the values of the first map?
You can use the putAll(fromMap) method : https://developer.salesforce.com/docs/atlas.en-us.apexcode.meta/apexcode/apex_methods_system_map.htm
Map<String, String> map1 = new Map<String, String>();
map1.put('Red','FF0000');
Map<String, String> map2 = new Map<String, String>();
map2.put('Blue','0000FF');
// Add map1 entries to map2
map2.putAll(map1);
System.Debug(map2);
//map2 = {Blue=0000FF, Red=FF0000}
If you want to go the other way : map1.putAll(map2);

ClassCastException - java.lang.String cannot be cast to com.codename1.ui.Image

I am consuming a JSON string that contains an image object among other objects. From this I create a PropertyBusinessObject which has a the following
public final Property<EncodedImage, Profile> profilePic = new Property<>("profilePic", EncodedImage.class);
I have created a method in the PropertyBusinessObject
public EncodedImage getProfilePic() {
return profilePic.get();
}
I populate my data into the Property business object as follows:
profile.getPropertyIndex().populateFromMap((Map) profileObject);
When I try to display the image on the form using the following code,
ScaleImageLabel profilePic = new ScaleImageLabel(profile.getProfilePic()) {
#Override
protected Dimension calcPreferredSize() {
Dimension dimension = super.calcPreferredSize();
dimension.setHeight(Math.min(dimension.getHeight(), Display.getInstance().convertToPixels(40)));
return dimension;
}
};
profilePic.setBackgroundType(Style.BACKGROUND_IMAGE_SCALED_FILL);
container.add(BorderLayout.NORTH, profilePic);
I get a ClassCastException
Exception: java.lang.ClassCastException - java.lang.String cannot be cast to com.codename1.ui.Image
Can anyone help me resolve, or suggest another way of consuming the JSON string?
populateFromMap doesn't currently support Base64 images, I'll add that as an option as that use case makes sense. Should be there with the Friday update.

Parse string in json format from Kafka using Flink

What I want to do is reading a string in json format e.g.
{"a":1, "b":2}
using flink and then extract a specific value by its key, say 1.
Refer to here: https://ci.apache.org/projects/flink/flink-docs-release-1.2/dev/connectors/kafka.html
What I have done is:
val params = ParameterTool.fromArgs(args)
val env = StreamExecutionEnvironment.getExecutionEnvironment
val kafkaConsumer = new FlinkKafkaConsumer010(
params.getRequired("input-topic"),
new JSONKeyValueDeserializationSchema(false),
params.getProperties
)
val messageStream = env.addSource(kafkaConsumer)
But I am not quite sure how to move forward then. In the link above, it says I can use objectNode.get(“field”).as(Int/String/…)() to extract a specific value by key, but I wonder how can I do that?
Or there can be a completely different way to achieve what I want?
Thanks!
Apply data transformation on the data from Kafka like this:
messageStream.map(new MapFunction<ObjectNode, Object>() {
#Override
public Object map(ObjectNode value) throws Exception {
value.get("field").as(...)
}
})

Storing JSON document with AppEngine

I'm trying to store JSON document into the AppEngine datastore using Objectify as persistence layer. To be able to query for document values, instead of just inserting the whole document as String field, I created a MapEntity which looks like this:
#Entity(name="Map")
public class MapEntity {
#Id
private Long id;
private Map<String,String> field;
// Code omitted
}
Since eventually when "unrolled" every key-value in the JSON document can be represented with Map
Example:
String subText = "{\"first\": 111, \"second\": [2, 2, 2], \"third\": 333}";
String jsonText = "{\"first\": 123, \"second\": [4, 5, 6], \"third\": 789, \"fourth\":"
+ subText + "}";
I will have the map fields stored in the datastore:
KEY VALUE
field.first => 123
field.second => [4,5,6]
field.third => 789
field.fourth-first => 111
field.fourth-second => [2,2,2]
field.fourth-third => 333
If I use my parse() method:
Parse the JSON document using JSON.Simple library and then do a recursive parse:
private MapEntity parse(String root, MapEntity entity, Map json) {
Iterator iter = json.entrySet().iterator();
while (iter.hasNext()) {
Map.Entry entry = (Map.Entry) iter.next();
if (entry.getValue() instanceof Map){
entity = parse((String)entry.getKey()+"-", entity, (Map) entry.getValue());
System.out.println("Map instance");
} else {
entity.setField(root + String.valueOf(entry.getKey()), String.valueOf(entry.getValue()));
}
}
return entity;
}
My app works like this:
MapEntity jsonEntity = new MapEntity();
Map json = null;
json = (Map) parser.parse(jsonText, containerFactory); // JSON.Simple parser
jsonEntity = parse("", jsonEntity, json);
Problems I encounter are:
I can't use the "." dot in the Map key field, so I have to use the "-"
Also my approach in storing JSON document is not very efficient
If your JSON follows a strict format, you'd probably be better off constructing a class to represent your data format and serializing directly to and from that class using a library like Jackson. You can use that class directly as your entity class in Objectify, but whether you want to do depends on whether you want to:
Store and expose the exact same set of data
Tightly couple your storage and JSON representations
You could use JSONObject as a replacement for your MapEntity and store the json to google app engine as a string using the toString() method. Upon retrieval you could simply restore the JSONObject using the appropriate constructor. This, of course, limits your ability to index properties in app engine and query against them.
If you want Objectify to do this for you, you could register a Translator to take care of calling the toString() and reconstruction.

Is this a bug? #Outheader anootation is null but from exchange it is a Map

I tried #OutHeaders outHeaderBound - I inspected in debug, I could see it is null. If I initialize a new hashtable/map for outHeaderBound, the headers key/value were not propagated to downstream queues.
e.g code snippet:
public void populateCorrelationId(#Body String body, #Headers Map<String, Object> headers,
#OutHeaders Map<String, Object> outHeaderBound, Exchange exchange) {
Map<String, Object> outHeader = exchange.getOut().getHeaders();
String msgId = (String) headers.get(msgIdKey);
String currentCorrId = (String) headers.get(correlationIdKey);
I tried outHeader = exchange.getOut().getHeaders(), I got an empty map, and headers that I put in outHeader got propagated.
I expect that #OutHeader and exchange.getOut.getHeader() both must give an empty map rather then one giving null.
Is this a bug? or intended for some functionality.
Oops I could not submit screenshot image of debug session.
See this FAQ - http://camel.apache.org/using-getin-or-getout-methods-on-exchange.html
And see the javadoc of the getOut() method on Exchange, then you would see that getOut will lazy create empty message if it was null. And therefore one is null and the other is an empty map, as the latter is due, getOut created an empty message.
http://camel.apache.org/maven/current/camel-core/apidocs/org/apache/camel/Exchange.html

Resources