Can you recommend on a Json Deserializer that can deserialize into existing object (merge 2 objects)?
When the user submit a form I want to save that into the db this way:
this is the json from the client:
{"affiliateId":1,"name":"First Affiliate","email":"email#gmail.com","user.userName":"test","user.password":"pass-hashed","employee.employeeId":1}
Affiliate affiliateFromDb = affiliateApi.getFromDbById(1);
SomeDeserialization json = new SomeDeserialization();
affiliateFromDb = json.fromJson(affiliateFromJson , affiliateFromDb );//affiliateFromDb = target bean
Meaning that I want the affiliateFromJson to be interpolated into affiliateFromDb.
And than I will call
affiliateApi.save(affiliateFromDb);
Note that the json contains deep deserialize, user.userName
Thanks
Use Gson! In particular, see the Object Examples.
class BagOfPrimitives {
private int value1 = 1;
private String value2 = "abc";
private transient int value3 = 3;
BagOfPrimitives() {
// no-args constructor
}
}
BagOfPrimitives obj2 = gson.fromJson(json, BagOfPrimitives.class);
The only catch here — but you will have this same problem with any other JSON (de)serializer — is the nonstandard "deep" object format you want to work with. You would have to use something like this instead:
{"affiliateId":1,"name":"First Affiliate","email":"email#gmail.com","user": {"userName":"test","password":"pass-hashed"},"employee.employeeId":1}
http://www.json.org/javadoc/org/json/JSONObject.html
JSONObject jsonResponse = new JSONObject(responseString);
Related
Is there a way to make Jackson interpret single JSON object as an array with one element and vice versa?
Example, I have 2 slightly different formats of JSON, I need both to map to same Java object:
Format A (JSON array with one element):
points : [ {
date : 2013-05-11
value : 123
}]
Format B (JSON object, yes I know it looks "wrong" but it's what I'm given):
points : {
date : 2013-05-11
value : 123
}
Target Java object that both of the above should convert to:
//Data.java
public List<Point> points;
//other members omitted
//Point.java
class Point {
public String date;
public int value;
}
Currently, only A will parse properly to Data. I want avoid directly tampering with the JSON itself. Is there some configuration in Jackson I can tamper with in order to make it accept B ?
Try with DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY - it should work for you.
Example:
final String json = "{\"date\" : \"2013-05-11\",\"value\" : 123}";
final ObjectMapper mapper = new ObjectMapper()
.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
final List<Point> points = mapper.readValue(json,
new TypeReference<List<Point>>() {});
The Jackson 1.x-compatible version uses DeserializationConfig.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY. So the above answer changes to:
final String json = "{\"date\" : \"2013-05-11\",\"value\" : 123}";
final ObjectMapper mapper = new ObjectMapper()
.enable(DeserializationConfig.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
final List<Point> points = mapper.readValue(json,
new TypeReference<List<Point>>() {
});
System.out.println(points);
Can solve the above problem by this code is given below, this works
final ObjectMapper objectMapper = new
ObjectMapper().enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
objectMapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
try {
String jsonInString = objectMapper.writeValueAsString(products.get(j));
InventoryParser inventoryParser = objectMapper.readValue(jsonInString,
InventoryParser.class);
System.out.println(inventoryParser.getId());
}
catch (IOException e)
{
e.printStackTrace();
}
"InventoryParser" is a POJO Class.
"products.get(j)" is JSON String.
Is there a way to make Jackson interpret single JSON object as an array with one element and vice versa?
Example, I have 2 slightly different formats of JSON, I need both to map to same Java object:
Format A (JSON array with one element):
points : [ {
date : 2013-05-11
value : 123
}]
Format B (JSON object, yes I know it looks "wrong" but it's what I'm given):
points : {
date : 2013-05-11
value : 123
}
Target Java object that both of the above should convert to:
//Data.java
public List<Point> points;
//other members omitted
//Point.java
class Point {
public String date;
public int value;
}
Currently, only A will parse properly to Data. I want avoid directly tampering with the JSON itself. Is there some configuration in Jackson I can tamper with in order to make it accept B ?
Try with DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY - it should work for you.
Example:
final String json = "{\"date\" : \"2013-05-11\",\"value\" : 123}";
final ObjectMapper mapper = new ObjectMapper()
.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
final List<Point> points = mapper.readValue(json,
new TypeReference<List<Point>>() {});
The Jackson 1.x-compatible version uses DeserializationConfig.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY. So the above answer changes to:
final String json = "{\"date\" : \"2013-05-11\",\"value\" : 123}";
final ObjectMapper mapper = new ObjectMapper()
.enable(DeserializationConfig.Feature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
final List<Point> points = mapper.readValue(json,
new TypeReference<List<Point>>() {
});
System.out.println(points);
Can solve the above problem by this code is given below, this works
final ObjectMapper objectMapper = new
ObjectMapper().enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
objectMapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
try {
String jsonInString = objectMapper.writeValueAsString(products.get(j));
InventoryParser inventoryParser = objectMapper.readValue(jsonInString,
InventoryParser.class);
System.out.println(inventoryParser.getId());
}
catch (IOException e)
{
e.printStackTrace();
}
"InventoryParser" is a POJO Class.
"products.get(j)" is JSON String.
I have a Java POJO
public class TagBean {
private String type;
private String id;
public TagBean(String type, String id) {
this.type = type;
this.id = id;
}
// getters
// setters
}
I'm building pojo's and adding them to a List, as
....
List<TagBean> channelsList = new ArrayList<>();
List<TagBean> showsList = new ArrayList<>();
for each <business logic> {
if value=channels {
channelsList.add(new TagBean(...));
}
if value=shows {
showsList.add(new TagBean(...));
}
}
Gson gson = new GsonBuilder().create();
JsonObject tjsonObject = new JsonObject();
tjsonObject.addProperty("channels", gson.toJson(channelsList));
tjsonObject.addProperty("shows", gson.toJson(showsList));
JsonObject mainjsonObject = mainjsonObject.add("tags", tjsonObject);
return mainjsonObject;
My output is:
{
"tags": {
"channels": "[{\"type\":\"channel\",\"id\":\"channel\",\"name\":\"Channel\",\"parent\":\"SXM\"}]",
"shows": "[{\"type\":\"shows\",\"id\":\"shows\",\"name\":\"Shows\",\"parent\":\"SXM\"},{\"type\":\"shows\",\"id\":\"howard\",\"name\":\"Howard Stern\",\"parent\":\"shows\"},{\"type\":\"shows\",\"id\":\"howardstern\",\"name\":\"Howard Stern\",\"parent\":\"howard\"}]",
"sports": "[]"
}
}
How can i remove the backslashes? So the output is like:
{
"tags": {
"channels": " [{"type":"channel","id":"channel","name":"Channel","parent":"SXM"}]",
"shows": "[{"type":"shows","id":"shows","name":"Shows","parent":"SXM"},{"type":"shows","id":"howard","name":"Howard Stern","parent":"shows"}....
There were few other posts, but none explained this.
The problem is caused by this:
tjsonObject.addProperty("channels", gson.toJson(channelsList));
What that is doing is converting channelsList to a string containing a representation of the list in JSON, then setting the property to that string. Since the string contains JSON meta-characters, they must be escaped when the strings are serialized ... a second time.
I think that you need to do this instead:
tjsonObject.add("channels", gson.toJsonTree(channelsList));
That should produce this:
{
"tags": {
"channels":
[{"type":"channel","id":"channel","name":"Channel","parent":"SXM"}],
"shows":
[{"type":"shows","id":"shows","name":"Shows","parent":"SXM"},
{"type":"shows","id":"howard","name":"Howard Stern","parent":"shows"}
....
That is slightly different to what your question asked for, but it has the advantage of being syntactically valid JSON!
String mainJsonStr = mainjsonObject.toString();
mainJsonStr = mainJsonStr.replace("\\\\", ""); //replace the \
System.out.println(mainJsonStr);
The problem is that gson.toJson returns a String, and
tjsonObject.addProperty("channels", gson.toJson(channelsList));
this will add channels as a string and not as a JSON object.
One possible solution is to convert the string returned from gson.toJson to JSON object first then add it to the parent JSON object like
Gson gson = new GsonBuilder().create();
JsonObject tjsonObject = new JsonObject();
tjsonObject.put("channels", new JsonObject(gson.toJson(channelsList)));
tjsonObject.put("shows", new JsonObject(gson.toJson(showsList)));
this will treat channels and shows as JSON object
All strings in java have to escape quotes in them. So jsonInString should have slashes in it. When you output jsonInString though it shouldn't have the quotes. Are you looking at it in a debugger or something?
Just parse json directly and check - will get the output
above solution is not working anymore since GSON 2.8.*
use gson.toJsonTree(jsonText).getAsString(); instead
I need to be able to deserialize a JSON string produced by Jackson (Java/Spring server) with a C#/JSON.Net client while keeping the object references intact. Jackson uses "#id":1...n for cyclic references, while the reference is denoted by a single integer. JSON.Net uses "$id" and "$ref".
Does anybody know how to convert a JSON string from Jackson to a JSON.Net compatible version?
Here is my solution:
Use these settings for JSON.Net:
JsonSerializerSettings settings = new JsonSerializerSettings
{
PreserveReferencesHandling = PreserveReferencesHandling.Objects,
};
Use this interceptor to convert the references:
public static class JSONInterceptor
{
public static string sanitizeJSON(string originalJSONFromJava)
{
// Get ID right from Jackson to JSON.Net
string pattern = Regex.Escape(#"""#id"":") + "(\\d+)";
string replacement = #"""$id"":""$1""";
Regex rgx = new Regex(pattern);
string output = rgx.Replace(originalJSONFromJava, replacement);
// Convert Jackson reference in array
pattern = #",(\d+)";
replacement = #",{""$ref"":""$1""}";
rgx = new Regex(pattern);
output = rgx.Replace(output, replacement);
// Convert single Jackson reference to ref
pattern = Regex.Escape(#"""\\w+"":") + "(\\d+)";
replacement = #"""$ref"":""$1""";
rgx = new Regex(pattern);
output = rgx.Replace(output, replacement);
return output;
}
}
Call the interceptor and deserialize like this:
asset = JsonConvert.DeserializeObject<Asset>(JSONInterceptor.sanitizeJSON(response), settings);
The asset class has this layout:
public class Asset {
....
// Parent asset
public Asset parent;
// Asset agents
public List<Agents> agent;
....
}
So, Jackson produces something like:
{"#id":1,......."parent":{"#id":15,.....},"agents":[{"#id":6, ......},12,{...}]...}
which needs to be converted into something like (JSON.Net):
{"$id":"1",...,"$ref":"15",....,"agents":[{...,"$ref":"6",...]}
This is what the code above does.
Hope this helps somebody.
We have to parse a json structure similar to below.
project {
header {
}
pool {
}
cmp {
name = "";
id = "";
desc = "";
cmp [
{
name = "";
id = "";
desc = "";
}
{
name = "";
id = "";
desc = "";
}
{
name = "";
id = "";
desc = "";
cmp [
{
name = "";
id = "";
desc = "";
}
}
}
}
The issue is, cmp element is present in the json infinitly (and it is recursive too).
The cmp element contains lots of properties other than name, id and desc. But we need only name, id and desc to extract from the jSON.
I can able to parse the JSON string using com.json.parsers.JSONParser. But populating the parsed JSON to a model class/bean class is not working. It may be a simple logic. But I cannot. Please help...
The json file is generated as an output of one modeling software.
I want to parse this, using java. Can somebody help me to parse this?
Hope I have explained the issue correctly. Your help will be helpful for us.
You can do this with Jackson, just create your object with all the fields that may or may not be present in the message. All the fields not present in the message will end up as null (or default value for primitives) in the resulting object.
Just have the object contain a copy of itself and that will handle the recursion
#XmlRootElement
public class Foo {
Foo recursiveFoo; // will be null or another instance of Foo
int intData; // Will be 0 or an integer value
String strData; // Will be null or a String value
// Getters and setters here
}
Take a look at Google Gson library. With it you can do things like:
class BagOfPrimitives {
private int value1 = 1;
private String value2 = "abc";
private transient int value3 = 3;
BagOfPrimitives() {
// no-args constructor
}
}
//(Serialization)
BagOfPrimitives obj = new BagOfPrimitives();
Gson gson = new Gson();
String json = gson.toJson(obj);
//==> json is {"value1":1,"value2":"abc"}
//(Deserialization)
BagOfPrimitives obj2 = gson.fromJson(json, BagOfPrimitives.class);
//==> obj2 is just like obj