How to populate a custom attribute in ProdctData JSON? - java

I am trying to fetch product data based on some request criteria. When I am converting the productmodel to productdata using convertors and populators i am getting all the product data in response.
I had tried to set the string value while converting & populating the productmodel data to productdata but its not helpful!!
{
"products": [
{
//Getting from Product Model
"name" : "ABC"
"desc" : "abcde"
"Quantity": 2"
//Not from Product Model
"matcode" : "001100"
},
]
}
is it possible to set one more string value(String matcode ="ABC") inside the same response?

Ideally, if you set matcode(a attribute) in ProductData correctly it gets reflected in the response
Decare matcode attribute inside ProducctData by declaring it in your *beans.xml, something like.
<bean class="de.hybris.platform.commercefacades.product.data.ProductData">
<!-- other attributes -->
<property name="matcode" type="java.util.Set<java.lang.String>"/>
</bean>
Now inside populator, set the matcode attribute value and you are done. Debug your controller and see whether you custom attribute value is there in product data. If it's there then it'll get converted to JSON correctly.
#Override
public void populate(final SOURCE productModel, final TARGET productData) throws ConversionException
{
//... other codes
productData.setMatcode("001100"); // add your logic to set this value
}

If you're using hql, you can do it like:
#Entity
#Table(name = "product")
public class Product {
#Column(name = "name")
private String name;
#Column(name = "desc")
private String desc;
#Column(name = "quantity")
private Integer quantity;
#Transient
#Column(name = "quantity")
private String matcode;
public Product(String name, String desc, Integer quantity, String matcode) {
this.name = name;
this.desc = desc;
this.quantity = quantity;
this.matcode = matcode;
}
}
If you want to read more about Transient annotation, please follow Transient Attribute

You can use a library like gson.
Assuming you have model like this:
public class Products
{
private List<Product> products;
}
public class Product
{
private String name;
private String desc;
private String Quantity;
}
Easy way:
Add another attribute to Product model
private String matcode;
Now below code could be used:
Gson gson = new Gson();
String jsonOutput = "{\"products\": [{ \"name\" : \"ABC\" ,\"desc\" : \"abcde\", \"Quantity\": \"2\"}]}";
Products products = gson.fromJson(jsonOutput, Products.class);
System.out.println(products);
for(Product p : products.getProducts()){
p.setMatcode("001100");
}
System.out.println(gson.toJson(products));
Another longer path :
a. read the JSON response
b. convert to object ( which you should be already doing )
c. use gson to convert object to JsonElement as array
d. iterate and update the JsonObject as you require
e. convert the updated JsonElement to String output.
Working code below:
Gson gson = new Gson();
String jsonOutput = "{\"products\": [{ \"name\" : \"ABC\" ,\"desc\" : \"abcde\", \"Quantity\": \"2\"}]}";
Products products = gson.fromJson(jsonOutput, Products.class);
System.out.println(products);
JsonElement jsonElement = gson.toJsonTree(products);
JsonArray jsonArray = jsonElement.getAsJsonObject().get("products").getAsJsonArray();
for (JsonElement ele : jsonArray) {
JsonObject obj = ele.getAsJsonObject();
obj.addProperty("matcode", "001100");
}
String updatedJsonOutput = gson.toJson(jsonElement);
System.out.println("Updated json Object: " + updatedJsonOutput);

Related

Convert String data from mysql table to json list in java

I want to convert a string to json list. I am currently working on a web api using spring boot. There is a table which contains multiple value at a ssingle column and similarly all the columns are having multi values. Like: There is a car company. There is a column named models - which contains more than one models and then there there is a price column which contains all the models price respectively.
Now I have to convert those strings to json format.
I tried using the split() in java for that but that is giving the address location as output.
Model class
..........//getters and setters and declarations
#Override
public String toString() {
String ar = car_type;
String ar1[]=ar.split(",");
int l = ar1.length;
return "{" +
"\"car_comp\":" +"\"" + car_comp+ "\""+"," +
"\"car_type\":" +"\""+ ar1 + "\""+","+
"\"car_price\":" +"\""+ car_price+ "\""+","+
"\"car_comp_value\":"+"\"" + car_comp_value +"\""+
'}';
}
I used the length function to check whether the array is being created of the right size or not.
The Output
"car_comp": {
"car_comp": "bmw",
"car_type": "[Ljava.lang.String;#4017b770",
"car_price": "$1500",
"car_comp_value": "$65.4M"
}
PLEASE IGNORE THE DATA..
But the car type is showing not what I expected.
To be honest this is my first time working in web api and json and I don't have much idea how to do things with it.
The Expected Output :
"car_comp": {
"car_comp": "bmw",
"car_type": [{modelA},{modelB},{modelC}],
"hb_unit_hints": "Kg",
"hb_value": "65.4"
}
Thanks in Advance.
String ar = car_type;
String ar1[]=ar.split(",");
There, I feel your problem is trying to map a String column of a table entity to a List model field. If you had a car model with List field then model to JSON string conversion is straight-forward using jackson-objectmapper like:
Car model:
public class Car {
String car_comp;
List<String> car_type;
String car_price;
String car_comp_value;
}
Converting Car model object to JSON string:
ObjectMapper objectMapper = new ObjectMapper();
Car car = new Car();
car.car_comp = "BMW";
car.car_type = Arrays.asList("modelA", "modelB", "modelC");
car.car_price = "$1500";
car.car_comp_value = "$65.4M";
String json = objectMapper.writeValueAsString(car);
If you are using JPA Entity to map database tables to models, you can use javax.persistence.AttributeConverter to convert a comma-separated String column to a List field of the entity, like:
Custom attribute converter:
public class CarTypeConverter implements AttributeConverter<List<String>, String> {
#Override
public Long convertToDatabaseColumn(List<String> attribute) {
if (attribute == null) return null;
return attribute.stream().reduce((x, y) -> x + "," + y).orElse("");
}
#Override
public List<String> convertToEntityAttribute(String dbColumnValue) {
if (dbColumnValue == null) return null;
String[] typeArray = dbColumnValue.split(",");
List<String> typeList = Arrays.stream(typesArray).collect(Collectors.toList());
return typeList;
}
}
Car database entity:
#Entity
#Table(name = "car_comp")
class Car {
#Column(name = "car_comp")
String car_comp;
#Column(name = "car_type")
#Convert(converter = CarTypeConverter.class)
List<String> car_type;
#Column(name = "car_price")
String car_price;
#Column(name = "car_value")
String car_comp_value;
//getters and setter below...
}
Since you are using spring boot, You could implement that using ObjectMapper.
So I will just create model for clear explanation
Car Model
class Car {
#JsonProperty(value = "car_company")
private String carCompany;
#JsonProperty(value = "car_type")
private List<CarType> carType;
#JsonProperty(value = "car_price")
private String carPrice;
// Getter, Setter, All Args
}
Car Type
class CarType {
#JsonProperty(value = "type")
private String type;
//Getter, Setter, All Args
}
Implementation
ObjectMapper mapper = new ObjectMapper();
List<CarType> carTypes = Arrays.asList(new CarType("SEDAN"), new CarType("HATCHBACK"));
Car car = new Car("Telsa", carTypes, "1000");
System.out.println(mapper.writeValueAsString(car));
//Output :
//{"car_company":"Telsa","car_type":[{"type":"SEDAN"},{"type":"HATCHBACK"}],"car_proce":"1000"}
JsonNode jsonNode = mapper.valueToTree(car);
// It also gives you JsonNode

Unable to convert JSON object to Java Object correctly

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
}

Serialize only the data you need from json

I get some data form JSON. I can't change JSON, it is foreign API. JSON...
"apply" : {
"type" : "submit",
"form" : "#pageForm",
"data" : {
"ctl00$MainContentArea$fld_offerCode" : "%promo"
},
"submit" : "#OfferCodeSubmit",
"response" : {
"type" : "html",
"total" : "#orderItemsDisplay .totals:last"
}
},
or
"apply" : {
"type" : "post",
"url" : "https:\/\/www.4wheelparts.com\/shoppingcart.aspx",
"submit" : "#ctl00_ContentPlaceHolder1_btnCouponCode",
"contentType" : "application\/x-www-form-urlencoded",
"data" : {
"__VIEWSTATE" : "",
"ctl00$ContentPlaceHolder1$tbCouponCode" : "%promo",
"ctl00$ContentPlaceHolder1$btnCouponCode" : "Redeem"
}
}
I want save JSON to database, and use "serialize data". But parameter "data" constantly changing. How can I serialize parameter "type", "url", "submit", and is't serialize parametr "data"?
I want to add to my DB this form...
"type" : "post"
"url" : "https:\/\/www.4wheelparts.com\/shoppingcart.aspx"
"data" : {
"__VIEWSTATE" : "",
"ctl00$ContentPlaceHolder1$tbCouponCode" : "%promo",
"ctl00$ContentPlaceHolder1$btnCouponCode" : "Redeem"
}
So I serialize the data...
public class Apply
{
#SerializedName("type")
#Expose
private String type;
#SerializedName("submit")
#Expose
private String submit;
#SerializedName("timeout")
#Expose
private Long timeout;
....How data should look like???
Or am I going to need to move the another way?
dont add data in your model and that will be ok. i suggest you to use Gson library. and do as below :
Apply apply = (new Gson()).fromJson(jsonString);
jsonString is a string variable containing your json.
you can import Gson library by adding this to your gradle file:
compile 'com.google.code.gson:gson:2.8.0'
If you need only few specific data,Can follow this
jsonObj = new JSONObject(strRequestPacket);
requiredData = jsonObj.getString("requiredData");
If you need to map to your entity class,then follow this
Gson gson = new Gson();
if(mob_farmerStatus !=null){
User user = gson.fromJson(strRequestPacket, User.class);
System.out.println("user:::"+user);
public class Apply
{
#SerializedName("type")
#Expose
private String type;
#SerializedName("submit")
#Expose
private String submit;
#SerializedName("timeout")
#Expose
private Long timeout;
#SerializedName("timeout")
#Expose
private Data data;
// Setter Getters here
}
public class Data
{
private String vIEWSTATE;
private String ctl00$ContentPlaceHolder1$tbCouponCode;
private String ctl00$ContentPlaceHolder1$btnCouponCode;
private Map<String, Object> additionalProperties = new HashMap<String, Object>();
public String getVIEWSTATE() {
return vIEWSTATE;
}
public void setVIEWSTATE(String vIEWSTATE) {
this.vIEWSTATE = vIEWSTATE;
}
public String getCtl00$ContentPlaceHolder1$tbCouponCode() {
return ctl00$ContentPlaceHolder1$tbCouponCode;
}
public void setCtl00$ContentPlaceHolder1$tbCouponCode(String ctl00$ContentPlaceHolder1$tbCouponCode) {
this.ctl00$ContentPlaceHolder1$tbCouponCode = ctl00$ContentPlaceHolder1$tbCouponCode;
}
public String getCtl00$ContentPlaceHolder1$btnCouponCode() {
return ctl00$ContentPlaceHolder1$btnCouponCode;
}
public void setCtl00$ContentPlaceHolder1$btnCouponCode(String ctl00$ContentPlaceHolder1$btnCouponCode) {
this.ctl00$ContentPlaceHolder1$btnCouponCode = ctl00$ContentPlaceHolder1$btnCouponCode;
}
public Map<String, Object> getAdditionalProperties() {
return this.additionalProperties;
}
public void setAdditionalProperty(String name, Object value) {
this.additionalProperties.put(name, value);
}
}
I solved it problem with help:
import okhttp3.ResponseBody;
public interface ConfigsBodyRequest
{
#GET("config.json")
Observable<ResponseBody> getResponse();
}
I get json without serialization, and than parse json
//item - (String) content of json file.
JSONObject jsonObject = new JSONObject(item);
String required = jsonObject.getString("apply");
And now required is equal to String : {"type":"submit","form":"#pageForm","data":{"ctl00$MainContentArea$fld_offerCode":"%promo"}},
And i just save in DB this string, this is what I needed. Thanks all.

Why does jsonParser.getCodec().readTree(jsonParser).asText() return an empty String for me?

I wrote an REST service to ingest metadata from post requests. I am using spring-data-elasticsearch, and I made a custom Metadata Object to deserialize Json into that looks like this:
#Document(indexName = "metadata_v1", type = "metadata")
public class Metadata {
#Id
private String id;
#Field(type = FieldType.String)
private String uuid;
#Field(type = FieldType.String)
private String userId;
#Field(type = FieldType.Date, format = DateFormat.basic_date_time)
private Date date = null;
#Field(type = FieldType.String)
private String classification;
#Field(type = FieldType.Nested)
private List<NumericKeyValue> numericKeyValue;
#Field(type = FieldType.Nested)
private List<TextKeyValue> textKeyValue;
with a bunch of getters and setters.
It works fine for all of its fields except numericKeyValue and textKeyValue Json Arrays. I couldn't send those in via post request, and realized I needed to write a deserializer. I did that for numericKeyValue, and as far as I've read, it's supposed to look like this:
public class NumericKeyValueJsonDeserializer extends JsonDeserializer<List<NumericKeyValue>>{
#Override
public List<NumericKeyValue> deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
TypeReference<List<NumericKeyValue>> typeRef = new TypeReference<List<NumericKeyValue>>(){};
ObjectMapper mapper = new ObjectMapper();
JsonNode root = jp.getCodec().readTree(jp);
String numericKeyValue = root.get("numericKeyValue").asText();
return mapper.readValue( numericKeyValue, typeRef);
}
}
And I added
#JsonDeserialize(using = NumericKeyValueJsonDeserializer.class)
to the field declaration in my Metadata class.
However, after a lot of testing, I have come to realize that the JsonNode root not only doesn't contain "numericKeyValue", but gives me a completely empty string when I invoke root.asText().
I have been using Postman to send in a post request to my endpoint
#RequestMapping(value="/metadata_v1/ingest", method=RequestMethod.POST, consumes="application/json")
public #ResponseBody Metadata createEntry(#RequestBody Metadata entry){
repository.save(entry);
return entry;
}
containing the following Json:
{
"numericKeyValue":
[
{
"key": "velocity",
"value": 55.5
},
{
"key": "angle",
"value": 90
}
]
}
My mapping looks like this:
"numericKeyValue" : {
"type" : "nested",
"properties" : {
"key" : {"type" : "string"},
"value" : {"type" : "double"}
}
}
I can show more things if needed. I think I will be fine if I can just get the JSON I send in Java somehow, perhaps as a String. I've been getting empty Strings that result in null pointer exceptions and when I tried String numericKeyValue = jp.getText() the String was just the current token of "[", which I guess at least isn't an empty String, but still doesn't help me.
Any help or advice is much appreciated.
In your case the value for numericKeyValue is an array. You should replace the following line:
String numericKeyValue = root.get("numericKeyValue").asText();
with:
if ( root.isArray() ){
// loop trough array
for (final JsonNode node : root){
String numericKeyValue = node.get("numericKeyValue").asText();
// then build the list to be returned
}
}

How can I deserialize a JSON array of "name" "value" pairs to a Pojo using Jackson

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.

Categories

Resources