I am storing a json string into a text field in mysql.
After the insertion, i want to update my json string and add the mysql line id into it with jackson json.
I have a java String which is in Json format
{
"thing":"val"
}
I'm looking to add another K/V without writing lines of codes.
to finally have this :
{
"thing":"val"
"mysqlId":10
}
I can convert my String to a JsonNode :
ObjectMapper mapper = new ObjectMapper();
JsonNode json = mapper.readTree( jsonStr);
Looking to do something like this
json.put("mysqlId",10);
json.toString();
then update in my text field with new json string in mysql
I can't make it.
I don't want use many class is there a simple way to do so with jackson?
Try casting your JsonNode to an com.fasterxml.jackson.databind.node.ObjectNode and then calling put set (or replace) on it.
Related
My servlet recieves/loads multiple parameters from/for an article (price, id, count, name).
While they are saved in the session for other purposes I want to display them in a Shopping cart.
So my idea was to get all values into a json like this
{"id":1, "prductName":"article1"}
but my json always ends up empty.
I had two approaches:
String prname = request.getParameter("name");
String anz = String.valueOf(session.getAttribute("Anzahl"));
String prid = request.getParameter("id");
String price = request.getParameter("price");
These are my parameters:
First try:
class ToJson{
String prname1 = String.valueOf(session.getAttribute("prname"));
String anz1 = String.valueOf(session.getAttribute("Anzahl"));
String prid1 = String.valueOf(session.getAttribute("id"));
String price1 = String.valueOf(session.getAttribute("price"));
}
ToJson obj = new ToJson();
Jsonb jsonb = JsonbBuilder.create();
String jsn1 = jsonb.toJson(obj);
Ends up with: {}
Second try:
ArrayList<String> ar = new ArrayList<String>();
ar.add(prname);
ar.add(price);
ar.add(prid);
ar.add(anz);
ToJson obj = new ToJson();
Jsonb jsonb = JsonbBuilder.create();
String jsn = jsonb.toJson(ar);
Ends up with: ["P1neu","25","1","145"]
It isn't in a format I wanted and I also don't know how to access the seperate values here, I tried jsn[1] but it didnt work.
Could you help me, please?
To your first question, why JSON object is printing empty:
You are missing getters & setters in the ToJSON class for JSON Builder/Parser to access the properties/fields, and that's why its printing as empty object.
To your second question, how do I access JSON properties:
JSON representation is a natively a string representation, and you can't read part of string as jsn[1].
For reading JSON object properties, you convert it into POJO using available any of preferred open source parser libraries like Jacksons, Gson etc. And then access POJO properties using standard java getter/setters.
I have a malformed json array string which I get from an API call as follows:
[{\"ResponseCode\":1,\"ResponseMsg\":\"[{\"Code\":\"CA2305181\",\"Message\":\"Processed successfully\"}]\"}]
There is a double quote before open square bracket in the value of Response Msg property.
Is there a way to convert this into Java object ?
What I have tried so far:
I have used Jackson to parse it as follows but it gives error
ObjectMapper mapper = new ObjectMapper();
mapper.setPropertyNamingStrategy(new ResponseNameStrategy());
Response[] response = mapper.readValue(strOutput1, Response[].class);
Error: Can not deserialize instance of java.util.ArrayList out of VALUE_STRING token
I have also tried using Gson to parse it but it also gives error
Gson gson = new GsonBuilder()
.setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)
.create();
Response[] response = gson.fromJson(strOutput1, Response[].class);
Error: Expected BEGIN_ARRAY but was STRING at line 1 column 35 path $[0].ResponseMsg
I have gone through the following links on StackOverflow but none of them has addressed my issue:
How to Convert String Array JSON in a Java Object
Convert a JSON string to object in Java ME?
JSON Array to Java objects
Convert json String to array of Objects
converting 'malformed' java json object to javascript
I think the answer is in the comments, you appear to be trying to solve the issue on the wrong place.
You are receiving json which you wish to parse into java objects, unfortunately the json is malformed so will not parse.
As a general rule you should never be trying to solve the symptom, but should look for the root cause and fix that, it may sound trivial but fixing symptoms leads to messy, unpredictable, and unmaintainable systems.
So the answer is fix the json where it is being broken. If this is something or of your control, while you wait for the fix, you could put a hack in to fix the json before you parse it.
This way you won't compromise your parsing, and only have a small piece of string replacement to remove when the third party has fixed the issue. But do not go live with the hack, it should only be used during development.
As i mentioned in the comment, you should prepare your service response in order to parse it.
I implemented an example:
public class JsonTest {
public static void main(String args[]) throws JsonProcessingException, IOException{
String rawJson =
"[{\"ResponseCode\":1,\"ResponseMsg\":\"[{\"Code\":\"CA2305181\",\"Message\":\"Processed successfully\"}]\"}]";
String goodJson = "{"+rawJson.split("[{{.}]")[2]+"}";
ObjectMapper mapper = new ObjectMapper();
final ObjectNode node = mapper.readValue(goodJson, ObjectNode.class);
System.out.println("Pretty Print: " + mapper.writerWithDefaultPrettyPrinter().writeValueAsString(node));
System.out.println("Just code: " + node.get("Code"));
}
}
Which returns:
This is how I finally solved my issue:
String inputJsonStr = "[{\"ResponseCode\":1,\"ResponseMsg\":\"[{\"Code\":\"CA2305181\",\"Message\":\"Claim has been added successfully.\"}"
+ "]\"}]";
int indexOfRes = inputJsonStr.indexOf("ResponseMsg");
if(inputJsonStr.substring(indexOfRes+13,indexOfRes+14).equals("\""))
{
inputJsonStr = inputJsonStr.substring(0,indexOfRes+13) + inputJsonStr.substring(indexOfRes+14);
}
int indexOfFirstClosingSquare = inputJsonStr.indexOf("]");
if(inputJsonStr.substring(indexOfFirstClosingSquare+1, indexOfFirstClosingSquare+2).equals("\"")) {
inputJsonStr = inputJsonStr.substring(0, indexOfFirstClosingSquare+1)+inputJsonStr.substring(indexOfFirstClosingSquare+2);
}
Now inputJsonStr contains a valid json array which can be parsed into Java custom object array easily with gson as given in this SO link:
Convert json String to array of Objects
I have this json String
{"data":"[Level [key=LevelKey [keyEnd=0], Description=abc], Level [key=levelKey [keyEnd=1], Description=xyz]", "id":"123"}
And corresponding java classes are
public class Level {
public LevelKey key;
public String id;
}
public class LevelKey{
public String keyEnd;
}
I want to convert this data json string to list of Level object using Jackson
ObjectMapper mapper = new ObjectMapper();
List<Level> arr = mapper.readValue(data, new TypeReference<List<Level>>(){});
But I am getting below error
com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'Level': was expecting ('true', 'false' or 'null')
Is there any other method to parse it?
The below does not look like a proper JSON for the purpose (except for a standard fixed string)
"[Level [key=LevelKey [keyEnd=0], Description=abc], Level [key=levelKey [keyEnd=1], Description=xyz]"
You could correct the data part of your JSON to something like below (Closest to your JSON in question) :
[\"Level [key=LevelKey [keyEnd=0], Description=abc]\",\" Level [key=levelKey [keyEnd=1], Description=xyz]\"]
Is there any other method to parse it?
You could use a direct class reference of ArrayList instead of having to instantiate TypeReference like below to parse the above (corrected) json string :
List<Level> arr = mapper.readValue(data, (new ArrayList<Level>()).getClass());
This was an interesting one I must say. Take a look at code snippet I think I got it correct :
String data ="{\"data\":\"[Level [key=LevelKey [keyEnd=0], Description=abc], Level [key=levelKey [keyEnd=1], Description=xyz]\", \"id\":\"123\"}";
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
List<Level> arr = mapper.readValue(data, (new ArrayList<Level>()).getClass());
System.out.println(arr);
I got the following output :
[{data=[Level [key=LevelKey [keyEnd=0], Description=abc], Level [key=levelKey [keyEnd=1], Description=xyz], id=123}]
Also if you encountered any JsonParseException which according to documentation means :
Exception type for parsing problems, used when non-well-formed content
(content that does not conform to JSON syntax as per specification) is
encountered.
So while hacking the JSON you can update the ObjectMapper object like this :
mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true);
Also as mentioned by Exception_al using a direct class reference of ArrayList instead of having to instantiate TypeReference like below to parse the above (corrected) json string.
List<Level> arr = mapper.readValue(data, (new ArrayList<Level>()).getClass());
Hope this helped.
The String is not the JSON representation of what you expect you get deserialized into JAVA.
This is a JSON String:
"{"data":[{"key":{"keyEnd":0},"Description":"abc"},{"key":{"keyEnd":1},"Description":"abc"}],"id":"123"}"
So, there is either a problem with the String or you need to do the parsing yourself.
After deserializing my string and converting it to JSON using the code below:
JSONObject returnValue = new JSONObject();
String toJson = null;
try
{
Object otherObjectValue = SerializationUtils
.deserialize(myBytesArray);
Gson gson = new Gson();
toJson = gson.toJson(otherObjectValue);
returnValue.put(key, toJson);
}
some part of the JSON still has something like:
{ "key":"ATTRIBUTE_LIST", "value":"{\"attributeContract\":[{\"scope\":\"sso\",\"name\":\"SAML_SUBJECT\",\"description\":\"Click to Edit\",\"required\":true}]}"}
which means everything in:
"{\"attributeContract\":[{\"scope\":\"sso\",\"name\":\"SAML_SUBJECT\",\"description\":\"Click to Edit\",\"required\":true}]}"
is one string instead being another object with fields. Is there something I can do to sanitize by JSONObject to make it properly JSON?
The key part is OK, means the whole String is JSON formatted.
For the value part, /shows that the value of value is JSON formatted already.
So you may "deserialize" the value of value again to retrieve an Object result. Or you may ask the creator of origin JSON, to serialize origin Object one time into JSON format.
Because of the project requirement, I have to use com.fasterxml.jackson.databind library to parse JSON data cannot use other JSON libraries available.
I am new to JSON parsing, so not sure if there are better options here?
I would like to know how can I update a string value in an Array node in the JSON file.
Following is a sample JSON. Please note this is not the entire file content, it's a simplified version.
{
"call": "SimpleAnswer",
"environment": "prod",
"question": {
"assertions": [
{
"assertionType": "regex",
"expectedString": "(.*)world cup(.*)"
}
],
"questionVariations": [
{
"questionList": [
"when is the next world cup"
]
}
]
}
}
Following is the code to read JSON into java object.
byte[] jsonData = Files.readAllBytes(Paths.get(PATH_TO_JSON));
JsonNode jsonNodeFromFile = mapper.readValue(jsonData, JsonNode.class);
To update a root level node value e.g. environment in the JSON file , I found following approach on some SO threads.
ObjectNode objectNode = (ObjectNode)jsonNodeFromFile;
objectNode.remove("environment");
objectNode.put("environment", "test");
jsonNodeFromFile = (JsonNode)objectNode;
FileWriter file = new FileWriter(PATH_TO_JSON);
file.write(jsonNodeFromFile.toString());
file.flush();
file.close();
QUESTION 1: Is this the only way to update a value in JSON file and is it the best way possible? I'm concerned on double casting and file I/O here.
QUESTION 2: I could not find a way to update the value for a nested Array node e.g. questionList. Update the question from when is the next world cup to when is the next soccer world cup
You can use ObjectMapper to parse that JSON, it is very easy to parse and update JSON using pojo class.
use link to convert your json to java class, just paste your json here n download class structure.
You can access or update nested json field by using . (dot) operator
ObjectMapper mapper = new ObjectMapper();
String jsonString="{\"call\":\"SimpleAnswer\",\"environment\":\"prod\",\"question\":{\"assertions\":[{\"assertionType\":\"regex\",\"expectedString\":\"(.*)world cup(.*)\"}],\"questionVariations\":[{\"questionList\":[\"when is the next world cup\"]}]}}";
TestClass sc=mapper.readValue(jsonString,TestClass.class);
// to update environment
sc.setEnvironment("new Environment");
System.out.println(sc);
//to update assertionType
Question que=sc.getQuestion();
List assertions=que.getAssertions();
for (int i = 0; i < assertions.size(); i++) {
Assertion ass= (Assertion) assertions.get(i);
ass.setAssertionType("New Type");
}