Jackson build JSON from values, term? - java

The documentation in Jackson is horrible and it only states how it is possible to create JSON from objects and streams, not piece by piece. I cannot find the term to be able to search for more examples/documentation.
I would like to do something like the following.
JsonObject jsonObject = new JsonObject().add("type", "unregister").add("id",id);
return jsonObject.toString();
Which would return {"type":"unregister","id":2} as an example. Can anyone nudge me in the right direction?

The corresponding JsonObject in Jackson is ObjectNode. You can use its various xyzNode(...) factory methods to produce JsonNode subtype instances. You can then use ObjectNode#set(String, JsonNode) to add them.
JsonNodeFactory nc = new JsonNodeFactory(false); // or true, depending
ObjectNode root = new ObjectNode(nc);
TextNode text = root.textNode("unregister");
NumericNode id = root.numberNode(2);
root.set("type", text);
root.set("id", id);
Then
System.out.println(node);
produces
{"type":"unregister","id":2}
You can also create an ObjectNode through the ObjectMapper which uses the ObjectMapper's JsonNodeFactory.
ObjectMapper mapper = new ObjectMapper();
ObjectNode root = mapper.createObjectNode();

Jackson maps Java Objects to JSON, so their documentation is telling you what it does (it does not provide a sort of builder API to arbitrarily compose JSON documents)
If you want to map arbitrary key/values, use a Map<String, Object> and use Jackson to turn it into JSON. You can mix heterogeneous map values and get the result you want this way, pseudo:
Map<String, Object> map = new HashMap<>();
map.put("type", "unregister");
map.put("id", id);
StringWriter sw = new StringWriter();
mapper.writeValue(sw, map); // mapper is a ObjectMapper instance
System.out.println(sw.toString());

Related

get a key value pair from a String json (simple object)

Im trying to get a key:value pair from a simple jsonString to add it after into a memory tab. If facing an issue cause my input is a string. and it looks like my loop isnot able to read the key value pair.
I read many topics about it, and im still in trouble with it. As you can see below
{"nom":"BRUN","prenom":"Albert","date_naiss":"10-10-1960","adr_email":"abrun#gmail.com","titre":"Mr","sexe":"F"}
and my method, find only on object... the result is the same in my loop
public static ArrayHandler jsonSimpleObjectToTab(String data) throws ParseException {
if( data instanceof String) {
final var jsonParser = new JSONParser();
final var object = jsonParser.parse(data);
final var array = new JSONArray();
array.put(object);
final var handler = new ArrayHandler("BW_funct_Struct");
for( KeyValuePair element : array) {
handler.addCell(element);
Log.warn(handler);
}
return handler;
} else {
throw new IllegalArgumentException("jsonSimpleObjectToTab: do not support complex object" + data + "to Tab");
}
}
i also tryed before to type my array as a List, Object etc, without the keyValuePair object, i would appreciate some help.
Thanks again dear StackOverFlowers ;)
You can try this :
const json = '{"nom":"BRUN","prenom":"Albert","date_naiss":"10-10-1960","adr_email":"abrun#gmail.com","titre":"Mr","sexe":"F"}';
map = new Map();
const obj = JSON.parse(json,(key,value) => {
map.set(key,value)
});
and you'll have every pair stored in map
Simply split the whole line at the commas and then split the resulting parts at the colon. This should give you the individual parts for your names and values.
Try:
supposing
String input = "\"nom\":\"BRUN\",\"prenom\":\"Albert\"";
then
String[] nameValuePairs = input.split(",");
for(String pair : nameValuePairs)
{
String[] nameValue = pair.split(":");
String name = nameValue[0]; // use it as you need it ...
String value = nameValue[1]; // use it as you need it ...
}
You can use TypeReference to convert to Map<String,String> so that you have key value pair.
String json = "{\"nom\":\"BRUN\",\"prenom\":\"Albert\",\"date_naiss\":\"10-10-1960\",\"adr_email\":\"abrun#gmail.com\",\"titre\":\"Mr\",\"sexe\":\"F\"}";
ObjectMapper objectMapper = new ObjectMapper();
TypeReference<Map<String,String>> typeReference = new TypeReference<Map<String, String>>() {
};
Map<String,String> map = objectMapper.readValue(json, typeReference);
I just answered a very similar question. The gist of it is that you need to parse your Json String into some Object. In your case you can parse it to Map. Here is the link to the question with my answer. But here is a short version: you can use any Json library but the recommended ones would be Jackson Json (also known as faster XML) or Gson(by Google) Here is their user guide site. To parse your Json text to a class instance you can use ObjectMapper class which is part of Jackson-Json library. For example
public <T> T readValue(String content,
TypeReference valueTypeRef)
throws IOException,
JsonParseException,
JsonMappingException
See Javadoc. But also I may suggest a very simple JsonUtils class which is a thin wrapper over ObjectMapper class. Your code could be as simple as this:
Map<String, Object> map;
try {
map = JsonUtils.readObjectFromJsonString(input , Map.class);
} catch(IOException ioe) {
....
}
Here is a Javadoc for JsonUtils class. This class is a part of MgntUtils open source library written and maintained by me. You can get it as Maven artifacts or from the Github

Insert org.json.JSONArray into jackson ObjectNode

I have got stuck trying to insert a JSONArray into a Jackson ObjectNode. This is what I am trying to do:
public void myMethod(JSONArray jsonArray) {
ObjectNode payload = objectMapper.createObjectNode(0);
payload.put("array", /* jsonArray */);
payload.put(/* some other things */);
...
}
It feels like something really silly but what is actually the best way to do it?!
EDIT: I am sorry beacause I did not mention an important point, that is I have to serialize the ObjectNode once I finished building it, so using putPOJO() is not a possibility.
I like aribeiro's approach more. You can use the putPOJO() method to do this. For example:
// Incoming org.json.JSONArray.
JSONArray incomingArray = new JSONArray("[\"Value1\",\"Value2\"]");
ObjectMapper objectMapper = new ObjectMapper();
ObjectNode payload = objectMapper.createObjectNode();
// Adds the JSONArray node to the payload as POJO (plain old Java object).
payload.putPOJO("array", incomingArray);
System.out.println(objectMapper.writeValueAsString(payload));
Javadoc can be found here.
Note: here's a previous implementation that I submitted using readTree():
// Incoming org.json.JSONArray.
JSONArray incomingArray = new JSONArray("[\"Value1\",\"Value2\"]");
ObjectMapper objectMapper = new ObjectMapper();
ObjectNode payload = objectMapper.createObjectNode();
// Reads the JSON array into a Jackson JsonNode.
JsonNode jsonNode = objectMapper.readTree(incomingArray.toString());
// Sets the Jackson node on the payload.
payload.set("array", jsonNode);
System.out.println(objectMapper.writeValueAsString(payload));

how to parse a JSON string into ObjectNode in Jackson?

First of all could anyone explain to me What are differences between ObjectNode and JsonNode, and where they used?
Then if I want to convert a JSON string into ObjectNode what can I do?
You can do:
ObjectMapper mapper = new ObjectMapper();
JsonNode actualObj = mapper.valueToTree("{\"k1\":\"v1\"}")
JsonNode it is a super class of ObjectNode.
You can find the differences in the API.

Faster object json convertor

I have written a program which inserts in bulk to Elasticsearch in batch of around 3000. The problem is that I need to convert these object to json before executing the bulk insert request. But there is major downside with json convertion and it is becoming a bottle neck of my whole computation.
Can any one suggest a super fast way to convert object to json in java. My code looks like this:
private String getESValueAsString(ElasticSearchValue elasticSearchValue) throws JsonProcessingException {
ElasticSearchValue prevValue = null;
if (stateType == StateType.OPAQUE) {
prevValue = (ElasticSearchValue) elasticSearchValue.getPrevious();
}
elasticSearchValue.setPrevious(null);
ObjectMapper om = new ObjectMapper();
Map<String, Object> props = om.convertValue(elasticSearchValue, Map.class);
if (stateType == stateType.OPAQUE) {
props.put("previous", prevValue);
}
return om.writeValueAsString(props);
}
Just found the issue, I am creating too many ObjectMapper for each serialization and that is making my whole processing slow.
This is a very good guide and it improved my performance 100x
http://wiki.fasterxml.com/JacksonBestPracticesPerformance
why not just insert into BulkRequestBuilder json records in the first place, something like this
Client client = new TransportClient().addTransportAddress(new InetSocketTransportAddress("localhost", 9300));
BulkRequestBuilder bulk = client.prepareBulk();
.....
bulk.add(client.prepareIndex(<your index>, <your type>)
.setSource(<your object>.toJson());
....
and in <your object> class
create Gson like this:
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
and method:
public String toJson(){
return gson.toJson(this, <you class>.class);
}

How to parse a JSON string into JsonNode in Jackson?

It should be so simple, but I just cannot find it after being trying for an hour.
I need to get a JSON string, for example, {"k1":v1,"k2":v2}, parsed as a JsonNode.
JsonFactory factory = new JsonFactory();
JsonParser jp = factory.createJsonParser("{\"k1\":\"v1\"}");
JsonNode actualObj = jp.readValueAsTree();
gives
java.lang.IllegalStateException: No ObjectCodec defined for the parser, can not deserialize JSON into JsonNode tree
A slight variation on Richards answer but readTree can take a string so you can simplify it to:
ObjectMapper mapper = new ObjectMapper();
JsonNode actualObj = mapper.readTree("{\"k1\":\"v1\"}");
You need to use an ObjectMapper:
ObjectMapper mapper = new ObjectMapper();
JsonFactory factory = mapper.getJsonFactory(); // since 2.1 use mapper.getFactory() instead
JsonParser jp = factory.createJsonParser("{\"k1\":\"v1\"}");
JsonNode actualObj = mapper.readTree(jp);
Further documentation about creating parsers can be found here.
A third variant:
ObjectMapper mapper = new ObjectMapper();
JsonNode actualObj = mapper.readValue("{\"k1\":\"v1\"}", JsonNode.class);
Richard's answer is correct. Alternatively you can also create a MappingJsonFactory (in org.codehaus.jackson.map) which knows where to find ObjectMapper. The error you got was because the regular JsonFactory (from core package) has no dependency to ObjectMapper (which is in the mapper package).
But usually you just use ObjectMapper and do not worry about JsonParser or other low level components -- they will just be needed if you want to data-bind parts of stream, or do low-level handling.
import com.github.fge.jackson.JsonLoader;
JsonLoader.fromString("{\"k1\":\"v1\"}")
== JsonNode = {"k1":"v1"}
New approach to old question.
A solution that works from java 9+
ObjectNode agencyNode = new ObjectMapper().valueToTree(Map.of("key", "value"));
is more readable and maintainable for complex objects. Ej
Map<String, Object> agencyMap = Map.of(
"name", "Agencia Prueba",
"phone1", "1198788373",
"address", "Larrea 45 e/ calligaris y paris",
"number", 267,
"enable", true,
"location", Map.of("id", 54),
"responsible", Set.of(Map.of("id", 405)),
"sellers", List.of(Map.of("id", 605))
);
ObjectNode agencyNode = new ObjectMapper().valueToTree(agencyMap);

Categories

Resources