I am facing an issue while converting an JSON to a Java Object.
My Json is as below
{
"_id":{
"$oid":"5981428cf1aa82a313540b76"
},
"productId":1,
"name":"The Big Lebowski",
"currency":{
"currency":"USD",
"value":40.5
}
}
I am retrieving json as DBObject for Product from the MongoDB database.
DBObject dbObject = productsCollection.findOne(searchQuery);
if(dbObject != null)
{
Product product = (Product) AppUtils.fromDBObject(dbObject, Product.class);
return Optional.of(product);
}
Product is return as
Product[productId = 1, productName= null, currencyPrice = null]
My fromDBObject method in AppUtils.java is as below :
public static Object fromDBObject(DBObject dbObj, Class<?> clazz)
{
String json = dbObj.toString();
return new Gson().fromJson(json, clazz);
}
My POJO is as below :
public class Product
{
private long productId;
private String productName;
private CurrencyPrice currencyPrice;
// getter and setter
}
public class CurrencyPrice
{
private double value;
private String currency;
// getter and setter
}
I am unable to understand where it is going wroing for the DBObject object with json to translate to Product object.
Thanks !
try changing your POJO property names to match
public class Product
{
private long productId;
private String name;
private CurrencyPrice currency;
// getter and setter
}
Related
I have the following Json
{
"coreId" : "1",
"name" : "name",
"additionalValueList" : [
{
"columnName" : "allow_duplicate",
"rowId" : "10",
"value" : "1"
},
{
"columnName" : "include_in_display",
"rowId" : "11",
"value" : "0"
},
...e.t.c
]
},
...e.t.c
and Java class
class DTO {
#JsonProperty("coreId")
private Integer id;
private String name;
private Boolean allowDuplicate;
private Boolean includeInDisplay;
}
How I can easily map values from 'additionalValueList' to corresponding java fields.For example Json value from field 'columnName' - 'allow_duplicate' = DTO.allowDuplicate.
Actually I know how to do it with custom deserializers with #JsonDeserialize annotation and smth like this.Bu I have 40+ DTO and it is not a good idea to create own deserializer for each filed. I am looking for solution to have for example 1 deserializer(since values structure in 'additionalValueList' are the same for all entities) and to pass parameter(field name that I want to map to that field) to custom deserializer that will find in 'additionalValueList' entity with 'column Name' = parameter(that I passed from annotation) and return 'value'.
Example
class DTO {
#JsonProperty("coreId")
private Integer id;
private String name;
#JsonDeserialize(using = MyCustDeser.class,param = allow_duplicate)
private Boolean allowDuplicate;
#JsonDeserialize(using = MyCustDeser.class,param = include_in_display)
private Boolean includeInDisplay;
}
It will be a good solution but maybe not easy to achieve.However I will be very grateful for all your advices.Thank you.
Create a Converter class, then specify it on the DTO class.
The following code uses public fields for the simplicity of the example.
/**
* Intermediate object used for deserializing FooDto from JSON.
*/
public final class FooJson {
/**
* Converter used when deserializing FooDto from JSON.
*/
public static final class ToDtoConverter extends StdConverter<FooJson, FooDto> {
#Override
public FooDto convert(FooJson json) {
FooDto dto = new FooDto();
dto.name = json.name;
dto.id = json.coreId;
dto.allowDuplicate = lookupBoolean(json, "allow_duplicate");
dto.includeInDisplay = lookupBoolean(json, "include_in_display");
return dto;
}
private static Boolean lookupBoolean(FooJson json, String columnName) {
String value = lookup(json, columnName);
return (value == null ? null : (Boolean) ! value.equals("0"));
}
private static String lookup(FooJson json, String columnName) {
if (json.additionalValueList != null)
for (FooJson.Additional additional : json.additionalValueList)
if (columnName.equals(additional.columnName))
return additional.value;
return null;
}
}
public static final class Additional {
public String columnName;
public String rowId;
public String value;
}
public Integer coreId;
public String name;
public List<Additional> additionalValueList;
}
You now simply annotate the DTO to use it:
#JsonDeserialize(converter = FooJson.ToDtoConverter.class)
public final class FooDto {
public Integer id;
public String name;
public Boolean allowDuplicate;
public Boolean includeInDisplay;
#Override
public String toString() {
return "FooDto[id=" + this.id +
", name=" + this.name +
", allowDuplicate=" + this.allowDuplicate +
", includeInDisplay=" + this.includeInDisplay + "]";
}
}
Test
ObjectMapper mapper = new ObjectMapper();
FooDto foo = mapper.readValue(new File("test.json"), FooDto.class);
System.out.println(foo);
Output
FooDto[id=1, name=name, allowDuplicate=true, includeInDisplay=false]
I am using Jackson library to try and parse my JSON file. My JSON is actually an ARRAY of JSON Objects:
JSON ARRAY:
[
{
"Id" : "0",
"name" : "John"
},
{
"Id" : "1",
"name" : "Doe"
}
]
POJO CLASS:
#JsonIgnoreProperties(ignoreUnknown = true)
public class QuestData {
private String Id;
private String name;
public String getId() {
return Id;
}
public String getName() {
return name;
}
}
PARSING JSON:
private void parseJSON(File jsonFile) {
try {
byte[] jsonData = Files.readAllBytes(jsonFile.toPath());
System.out.println(new String(jsonData));
ObjectMapper mapper = new ObjectMapper();
List<QuestData> questDataList = mapper.readValue(jsonData, mapper.getTypeFactory().constructCollectionType(List.class, QuestData.class));
System.out.println("Read values: " + questDataList.get(0).getId());
} catch (IOException e) {
e.printStackTrace();
}
}
My first print statement prints correct Json data back (as String).
But next print statement says NULL. I even tried to itreate over entire list ot see if there is something that is not null, but with no luck.
I do not know what I am doing wrong here.
Jackson will by default use setter methods to set fields. So add setters like:
#JsonProperty("Id") // otherwise Jackson expects id for setId
public void setId(String id) {
Id = id;
}
Alternatively, tell Jackson to look for fields with this config:
mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
In this case Jackson will match the name of the field in the class Id with the one in JSON Id
Just add the #JsonProperty annotation to the Id property in your QuestData class:
#JsonIgnoreProperties(ignoreUnknown = true)
public class QuestData {
#JsonProperty("Id")
private String Id;
private String name;
public String getId() {
return Id;
}
public String getName() {
return name;
}
}
I am trying to deserialize some JSON which I got from the eBay API but I am getting the error: com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.lang.String out of START_ARRAY token
The JSON that is returned has many levels to it. e.g.
{"searchResult":[{"#count":"100","item":[{"itemId":["281492499859"],"title":["Panasonic Lumix TZ20 Digital Camera in Good Condition"],... etc
This is for a property called itemId in CompletedListing (class defined below)
I am calling this method with the line:
CompletedListingContainer listing = mapper.readValue(new File("C:\\resource\\jsonresult.txt"), CompletedListingContainer.class);`
Here are my classes.
CompletedListingContainer
public class CompletedListingContainer {
private ArrayList<CompletedListing> item;
private ArrayList<SearchResult> searchResult;
private List<String> paginationOutput;
#JsonIgnore
public List<String> getPaginationOutput() {
return paginationOutput;
}
public ArrayList<SearchResult> getSearchResult() {
return searchResult;
}
public ArrayList<CompletedListing> getItem() {
return item;
}
}
SearchResult
public class SearchResult {
#JsonProperty("#count")
private String count;
private ArrayList<CompletedListing> item;
#JsonIgnore
public String getCount() {
return count;
}
public ArrayList<CompletedListing> getItem() {
return item;
}
}
CompletedListing
public class CompletedListing {
#JsonProperty("itemId")
private String itemId;
private String title;
#JsonProperty("itemId")
public String getItemId() {
return itemId;
}
#JsonProperty("title")
public String getTitle() {
return title;
}
}
Any help would be greatly appreciated. Let me know if you need any more information.
{"itemId":["281492499859"] means your CompletedListing.itemId property should be a list or array.
put private ArrayList<CompletedListing> item in your SearchResult class and remove it from CompletedListingContainer
look at your json file structure:
{
"searchResult":[
{
"count":"100",
"item":[
{"itemId":["281492499859"]...
},
....
}
try this online tool to generate Java classes from json
I want to deserialize the following JSON object:
{
"id":"001",
"module_name":"Users",
"name_value_list":
{
"user_name": {"name":"user_name", "value":"admin"},
"full_name": {"name":"full_name", "value":"LluĂs Pi"},
"city": {"name":"full_name", "value":"Barcelona"},
"postal_code": {"name":"postal_code", "value":"08017"},
...
}
}
into some Java object like this:
#JsonIgnoreProperties(ignoreUnknown = true)
#JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE)
public class UserEntry
{
private String id;
private String moduleName;
private Person nameValueList;
public String getId()
{
return id;
}
public String getModuleName()
{
return moduleName;
}
public Person getPerson()
{
return nameValueList;
}
}
where Person is the following class:
#JsonIgnoreProperties(ignoreUnknown = true)
#JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE)
class Person
{
private String userName;
private String fullName;
private String city;
private String postalCode;
}
using Jackson but I get a deserialization error.
If I change the type of field nameValueList to a Map all the deserialization process goes with no problem and I get a map where the key is the "name" value and the value is the "value" value.
So my question is: is there any simple, or no so simple, way to deserialize this kind of JSON object to a Java Pojo with properties prop_1, prop_2, prop_3and prop_4?
{
"name_value_list":
{
"prop_1": {"name":"prop_1", "value":"value_1"},
"prop_2": {"name":"prop_2", "value":"value_2"},
"prop_3": {"name":"prop_3", "value":"value_3"},
"prop_4": {"name":"prop_4", "value":"value_4"},
...
}
}
Not very simple and not very clean. However you can do it by implementing a any setter field for the JSON attributes in the Person class which don't match any attribute on your UserEntry POJO.
#JsonAnySetter
public void putUserField(String userKey, Map<String, String> userValue)
throws NoSuchFieldException {
String actualFieldName = getActualFieldName(userKey);
Field field = this.getClass().getDeclaredField(actualFieldName);
field.setAccessible(true);
ReflectionUtils.setField(field, this, userValue.get("value"));
}
private String getActualFieldName(String userKey) {
return CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, userKey);
}
In addition to that, I had to change the Jackson attributes for the Person class to
#JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.PUBLIC_ONLY,
getterVisibility = JsonAutoDetect.Visibility.NONE)
for it to work for attributes like "city" which don't need any name transformation because jackson tries to directly set the field which fails.
I get the following json from a httpresponse
{
"result": "success",
"team_registration": {
"current_status": "executed",
"expiration_time": "2012-07-18T21:29:43Z",
"id": 609,
"team_id": 50,
}
}
How do I retreive the "result" as a string and the "team_registration" as a POJO (in Android) with Jackson?
Currently I have this:
HttpResponse response = httpClient.execute(httpGet);
if (response.getStatusLine().getStatusCode() == 200) {
HttpEntity entity = response.getEntity();
String json = EntityUtils.toString(entity);
Map<String, Object> map = mapper.readValue(json, new TypeReference<Map<String, Object>>() {
});
result = (String) map.get("result");
resultRegistration = (Registration) map.get("team_registration");
Registration class:
package be.radarwerk.app.model;
import java.io.Serializable;
import java.util.Date;
import org.codehaus.jackson.annotate.JsonIgnore;
public class Registration implements Serializable { // Todo implements parceable?
private static final long serialVersionUID = 1L;
private int id;
private String currentStatus;
private Date expirationTime;
#JsonIgnore
private Volunteer volunteer;
#JsonIgnore
private Team team;
public Registration() {
}
public Registration(int id, String currentStatus, Volunteer volunteer,
Team team) {
super();
this.id = id;
this.currentStatus = currentStatus;
this.volunteer = volunteer;
this.team = team;
}
public int getId() {
return id;
}
public String getCurrentStatus() {
return currentStatus;
}
public Volunteer getVolunteer() {
return volunteer;
}
public Team getTeam() {
return team;
}
public Date getExpirationTime() {
return expirationTime;
}
}
"result" as String works fine but for the "registration_moment" I get this exception:
java.lang.ClassCastException: java.util.LinkedHashMap cannot be cast to Registration
I also tried casting it to a String in the same way as "result" and doing mapper.readValue on that string.
No success.
Any tips?
Your class should be deserialized automatically if you modify it like this (Note! Jackson 2.1+ required):
#JsonIgnoreProperties("team_id")
#JsonNamingStrategy(PropertyNamingStrategy.LowerCaseWithUnderscoresStrategy)
public class Registration implements Serializable
{
private static final long serialVersionUID = 1L;
private int id;
private String currentStatus;
private Date expirationTime;
#JsonIgnore
private Volunteer volunteer;
#JsonIgnore
private Team team;
public Registration() {
}
// other code
}
Then, to deserialize in your code:
Registration registration;
final JsonNode node = mapper.readTree(json);
if (node.get("result").textValue().equals("success"))
registration = mapper.readObject(node.get("team_registration").traverse(),
Registration.class);
Your approach seems a bit odd to me. You should really be using the Android JSONObject class, that's what it's there for. Once you have a JSONObject (or JSONArray), you will need to iterate over it if you want to move elements into a different data structure, but that's very likely unnecessary.
In any event, here's some code (using android-query) to get you to a JSONObject:
String url = "whatever you want";
aq.ajax(url, JSONArray.class, new AjaxCallback<JSONArray>() {
#Override
public void callback(String url, JSONArray json, AjaxStatus status) {
if (json == null) {
Toast.makeText(context, "Failed to retrieve JSON", Toast.LENGTH_SHORT);
}
else {
try {
JSONObject general = json.getJSONObject(0);
...
}
}
}
});