nested for each loop to store data in json object - java

I am trying to store the data into json object in the below format:
{"mobile:":[{"price":"Rs. abc","name":"def"},{"price":"Rs. ghi","name":"jkl"},....}]}
I am trying in the below way but iam not getting desired output code is below:
Elements mobilename = document.select(
"#products div.product-unit div.pu-title ");
Elements price = document.select(
"#products div.product-unit div.pu-price div.pu-final span.fk-font-17");
for(Element url1:mobilename)
{
text=url1.text();
System.out.println(text);
for(Element b:price)
{
text1= b.text();
System.out.println(text1);
arr1.add(text1);
arr1.add(text);
}
pa.put("price",text1 );
pa.put("name", text);
obj7.add(pa);
}
json.put("mobile:", obj7);
I am getting the same mobile name and price in all the arrays.
Thank You.

I would use Jackson mapper for this. You can find it here
import com.fasterxml.jackson.databind.ObjectMapper;
public static class YourObject {
private List<Mobile> mobile;
// add getter + setter for mobile
}
public static class Mobile {
private String price;
private String name;
// add getter+setter for price and name
}
YourObject obj = new YourObject();
obj.setMobile(new Mobile[] { new Mobile("price1", "name1"), new Mobile("price2", "name2") });
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(obj);

Related

Jackson double serialized json string to Java object

I have a Json string which has a string message field.
String:
{ "Type" : "Text",
"Subject" : "data received",
"Message" :"{\\"language\\":\\"US\\",\\"data\\":\\"signature\\"}"
}
I want to convert it into the following structure:
Notification.java
public class Notification {
String type;
String subject;
Message message;
}
Message.java
public class Message {
String language;
String data;
}
Is there a way in which I can directly convert the string to a Java object of the above structure? I want to avoid deserializing twice.
You can create a custom Deserializer to deserialize the Message text into Message object and annotate the Message class with #JsonDeserialize:
#JsonDeserialize(using = MessageDeserializer.class)
public class Message {
String language;
String data;
}
public class MessageDeserializer extends JsonDeserializer<Message> {
public MessageDeserializer() {
super();
}
#Override
public Message deserialize(
final JsonParser jsonParser, final DeserializationContext deserializationContext) throws
IOException, JsonProcessingException {
final String messageText = jsonParser.getText();
// parse messageText into Message object
}
}
I am not sure my solution is acceptable since it does require additional explicit call to ObjectMapper to perform deserialization of the string value of Message.
However, this is it is done during the buildup of Notification object and does not require a String message property.
You need to add a ctor with String argument to Message class, where you can deserialize the String into Map and extract the instance propertieds:
public Message(String str) {
try {
#SuppressWarnings("unchecked")
Map<String, Object> map =
(Map<String, Object>)new ObjectMapper().readValue(str, Map.class);
language = map.containsKey("language") ? map.get("language").toString() : null ;
data = map.containsKey("data") ? map.get("data").toString() : null ;
} catch (Exception e) {
e.printStackTrace();
}
}
the new ctor will be called by Jackson when you deserialize a Notification object:
Notification n = (Notification)new ObjectMapper().readValue(reader, Notification.class);
You can convert json string into key-value pairs in Map.You will have to do twice as the Message value is again a json string.Use org.json for JSONObject
Map<String, String> map = new HashMap<String, String>();
JSONObject j = new JSONObject(str);
Iterator<String> keys = j.keys();
while( keys.hasNext() ){
String key = (String)keys.next();
String val = j.getString(key);
map.put(key, val);}
Then retrieve the values by iterating over the keys and pass the values into the class constructor
Then map.get(key) can be used to retrieve the values and will be passed into constructors of the classes.
The org.json library is easy to use:
//Create Json object to parse string
// str is input string
JSONObject obj = new JSONObject(str);
//Create Message
Message mess = new Message();
JSONObject obj2 = new JSONObject(obj.getString("Message"));
mess.data = obj2.getString("data");
mess.language = obj2.getString("language");
//Create Notification
Notification noti = new Notification();
noti.message = mess;
noti.subject = obj.getString("Subject");
noti.type = obj.getString("Type");

How to get the pure Json string from DynamoDB stream new image?

I've a Dynamodb table with streaming enabled. Also I've created a trigger for this table which calls an AWS Lambda function. Within this lambda function, I'm trying read the new image (Dynamodb item after the modification) from the Dynamodb stream and trying to get the pure json string out of it. My Question is how can i get the pure json string of the DynamoDB item that's been sent over the stream? I'm using the code snippet given below to get the new Image, but I've no clue how to get the json string out of it. Appreciate your help.
public class LambdaFunctionHandler implements RequestHandler<DynamodbEvent, Object> {
#Override
public Object handleRequest(DynamodbEvent input, Context context) {
context.getLogger().log("Input: " + input);
for (DynamodbStreamRecord record : input.getRecords()){
context.getLogger().log(record.getEventID());
context.getLogger().log(record.getEventName());
context.getLogger().log(record.getDynamodb().toString());
Map<String,AttributeValue> currentRecord = record.getDynamodb().getNewImage();
//how to get the pure json string of the new image
//..............................................
}
return "Successfully processed " + input.getRecords().size() + " records.";
}
}
Below is the complete code for converting from Dynamo JSON to Standard JSON:
import com.amazonaws.services.dynamodbv2.document.Item;
import com.amazonaws.services.dynamodbv2.document.internal.InternalUtils;
import com.amazonaws.services.dynamodbv2.model.AttributeValue;
import com.amazonaws.services.lambda.runtime.Context;
import com.amazonaws.services.lambda.runtime.RequestHandler;
import com.amazonaws.services.lambda.runtime.events.DynamodbEvent;
import com.amazonaws.services.lambda.runtime.events.DynamodbEvent.DynamodbStreamRecord;
import com.google.gson.Gson;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* Main Lambda class to receive event stream, parse it to Survey
* and process them.
*/
public class SurveyEventProcessor implements
RequestHandler<DynamodbEvent, String> {
private static final String INSERT = "INSERT";
private static final String MODIFY = "MODIFY";
public String handleRequest(DynamodbEvent ddbEvent, Context context) {
List<Item> listOfItem = new ArrayList<>();
List<Map<String, AttributeValue>> listOfMaps = null;
for (DynamodbStreamRecord record : ddbEvent.getRecords()) {
if (INSERT.equals(record.getEventName()) || MODIFY.equals(record.getEventName())) {
listOfMaps = new ArrayList<Map<String, AttributeValue>>();
listOfMaps.add(record.getDynamodb().getNewImage());
listOfItem = InternalUtils.toItemList(listOfMaps);
}
System.out.println(listOfItem);
try {
// String json = new ObjectMapper().writeValueAsString(listOfItem.get(0));
Gson gson = new Gson();
Item item = listOfItem.get(0);
String json = gson.toJson(item.asMap());
System.out.println("JSON is ");
System.out.println(json);
}catch (Exception e){
e.printStackTrace();
}
}
return "Successfully processed " + ddbEvent.getRecords().size() + " records.";
}
}
In c# you can convert newImage to pure json by use of DynamoDB Document class
using Amazon.DynamoDBv2.DocumentModel;
var streamRecord = dynamoEvent.Records.First();
var jsonResult=Document.FromAttributeMap(streamRecord.Dynamodb.NewImage).ToJson();
and if you want to go further ahead to convert json to object you can use Newtonsoft
using Newtonsoft.Json;
TModel model = JsonConvert.DeserializeObject(jsonResult);
Found a way of doing it cleanly. Using InternalUtils from aws-java-sdk-dynamodb-1.11.15.jar
com.amazonaws.services.dynamodbv2.model.Record streamRecord = ((RecordAdapter) record).getInternalObject();
// get order ready //
OrderFinal order = Utils.mapO2Object(
InternalUtils.toSimpleMapValue(streamRecord.getDynamodb().getNewImage().get("document").getM()),
OrderFinal.class );
Just summarizing the answer of Himanshu Parmar:
Map<String, AttributeValue> newImage = record.getDynamodb().getNewImage();
List<Map<String, AttributeValue>> listOfMaps = new ArrayList<Map<String, AttributeValue>>();
listOfMaps.add(newImage);
List<Item> itemList = ItemUtils.toItemList(listOfMaps);
for (Item item : itemList) {
String json = item.toJSON();
}
For those stuck with a Map<String, ?> where objects are plain Map, but not Attributes value, you can do the following:
Map<String, AttributeValue> dynamoDbAttributes =
objectMapper.convertValue(dynamoDbMap, new TypeReference<Map<String, AttributeValue>>() {});
and then convert this DynamoDB Map into a plain Map (equivalent to the json originally pushed into DynamoDb):
asMap = InternalUtils.toSimpleMapValue(dynamoDbAttributes);
For the ones facing issues with AttributeValue conversion refer the below code:
https://github.com/aws/aws-lambda-java-libs/blob/master/aws-lambda-java-events-sdk-transformer/README.md
Map<String, AttributeValue> stringAttributeValueMap = DynamodbAttributeValueTransformer.toAttributeValueMapV1(dynamodb.getNewImage());
List stringAttributeValueMapList = new ArrayList();
stringAttributeValueMapList.add(stringAttributeValueMap);
List<Item> listOfItem = InternalUtils.toItemList(stringAttributeValueMapList);
Gson gson = new GsonBuilder().setPrettyPrinting().create();
String updatedJSON = gson.toJson(listOfItem.get(0).asMap());
Below is the Method which converts DynamoDB JSON to normal JSON
/**
* Converts DynamoDB JSON to normal JSON.
*
* #param map Input map of String to AttributeValue.
* #return Returns an ObjectNode containing the normal JSON.
*/
public JsonObject toJsonObject(final Map<String, AttributeValue> map) {
final JsonNode result = mapToJsonObject(map);
final ObjectNode objectNode = (ObjectNode) result;
final ObjectMapper objectMapper = new ObjectMapper();
String recordObjectString;
try {
recordObjectString = objectMapper.writeValueAsString(objectNode);
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
final JsonParser jsonParser = new JsonParser();
final JsonObject jsonObject = jsonParser.parse(recordObjectString)
.getAsJsonObject();
return jsonObject;
}
So in your Case simple call below method like this
// here record is of type DynamodbStreamRecord
toJsonObject(record.getDynamodb().getNewImage());
This library do the job: dynamoDb-marshaler
var unmarshalJson = require('dynamodb-marshaler').unmarshalJson;
console.log('jsonItem Record: %j', unmarshalJson(record.dynamodb.NewImage));

Create JSONObject from POJO

I created a simple POJO:
public class LoginPojo {
private String login_request = null;
private String email = null;
private String password = null;
// getters, setters
}
After some searching I found this: JSONObject jsonObj = new JSONObject( loginPojo );
But with this I got the error:
The constructor JSONObject(LoginPojo) is undefined
I found another solution:
JSONObject loginJson = new JSONObject();
loginJson.append(loginPojo);
But this method does not exist.
So how can I convert my POJO into a JSON?
Simply use the java Gson API:
Gson gson = new GsonBuilder().create();
String json = gson.toJson(obj);// obj is your object
And then you can create a JSONObject from this json String, like this:
JSONObject jsonObj = new JSONObject(json);
Take a look at Gson user guide and this SIMPLE GSON EXAMPLE for more information.
It is possible to get a (gson) JsonObject from POJO:
JsonElement element = gson.toJsonTree(userNested);
JsonObject object = element.getAsJsonObject();
After that you can take object.entrySet() and look up all the tree.
It is the only absolutely free way in GSON to set dynamically what fields you want to see.
Jackson provides JSON parser/JSON generator as foundational building block; and adds a powerful Databinder (JSON<->POJO) and Tree Model as optional add-on blocks. This means that you can read and write JSON either as stream of tokens (Streaming API), as Plain Old Java Objects (POJOs, databind) or as Trees (Tree Model). for more reference
You have to add jackson-core-asl-x.x.x.jar, jackson-mapper-asl-x.x.x.jar libraries to configure Jackson in your project.
Modified Code :
LoginPojo loginPojo = new LoginPojo();
ObjectMapper mapper = new ObjectMapper();
try {
mapper.setVisibility(JsonMethod.FIELD, Visibility.ANY);
// Setting values to POJO
loginPojo.setEmail("a#a.com");
loginPojo.setLogin_request("abc");
loginPojo.setPassword("abc");
// Convert user object to json string
String jsonString = mapper.writeValueAsString(loginPojo);
// Display to console
System.out.println(jsonString);
} catch (JsonGenerationException e){
e.printStackTrace();
} catch (JsonMappingException e){
e.printStackTrace();
} catch (IOException e){
e.printStackTrace();
}
Output :
{"login_request":"abc","email":"a#a.com","password":"abc"}
JSONObject input = new JSONObject(pojo);
This worked with latest version.
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20180130</version>
</dependency>
You can also use project lombok with Gson overriding toString function. It automatically includes builders, getters and setters in order to ease the data assignment like this:
User user = User.builder().username("test").password("test").build();
Find below the example class:
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import com.google.gson.Gson;
#Data
#Builder(toBuilder = true)
#AllArgsConstructor
#NoArgsConstructor
public class User {
/* User name. */
private String username;
/* Password. */
private String password;
#Override
public String toString() {
return new Gson().toJson(this, User.class);
}
public static User fromJSON(String json) {
return new Gson().fromJson(json, User.class);
}
}
Simply you can use the below solution:
ObjectMapper mapper = new ObjectMapper();
String str = mapper.writeValueAsString(loginPojo);
JSONObject jsonObject = new JSONObject(str);
I use jackson in my project, but I think that u need a empty constructor.
public LoginPojo(){
}
You can use
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.13</version>
</dependency>
To create a JSON object:
#Test
public void whenGenerateJson_thanGenerationCorrect() throws ParseException {
JSONArray jsonArray = new JSONArray();
for (int i = 0; i < 2; i++) {
JSONObject jsonObject = new JSONObject();
jsonObject.put("AGE", 10);
jsonObject.put("FULL NAME", "Doe " + i);
jsonObject.put("DATE OF BIRTH", "2016/12/12 12:12:12");
jsonArray.add(jsonObject);
}
String jsonOutput = jsonArray.toJSONString();
}
Add the annotations to your POJO class like so:
#JSONField(name = "DATE OF BIRTH")
private String dateOfBirth;
etc...
Then you can simply use:
#Test
public void whenJson_thanConvertToObjectCorrect() {
Person person = new Person(20, "John", "Doe", new Date());
String jsonObject = JSON.toJSONString(person);
Person newPerson = JSON.parseObject(jsonObject, Person.class);
assertEquals(newPerson.getAge(), 0); // if we set serialize to false
assertEquals(newPerson.getFullName(), listOfPersons.get(0).getFullName());
}
You can find a more complete tutorial on the following site:
https://www.baeldung.com/fastjson

How to convert a list of objects to a JSON object?

I have a HashSet of objects that I am trying to put on a JSON object.
HashSet<Users> users;
...
JSONObject j = new JSONObject();
j.put("users", users);
However,
System.out.println(j.toString(2));
is giving me
{"users": [
{},
{}
]}
when there are 2 entries in the HashSet. The non-null values of Users objects are not there.
Is there more to converting a List of a declared type to a JSONObject?
I am using the JSON at org.json.*.
The Users class is as follows:
public class Users {
byte[] pic;
String firstName;
String lastName;
String address;
}
I'm seeing the entries in the HashSet "users" fine every otherwise.
TIA.
The problem is with your Users class. You appear to be expecting it to just pick up the fields, but I don't believe JSONObject does that - instead, it finds bean-like getters.
If you try to convert a single instance of your Users class to a JSONObject you get exactly the same result ({}) - this problem has nothing to do with trying to convert multiple instances. (It would be worth taking a lesson from this about diagnosing problems - always try to reduce the scope.)
As soon as you create a class with appropriate getters, it works fine. Sample code:
public final class User {
private final String firstName;
private final String lastName;
public User(String firstName, String lastName) {
this.firstName = firstName;
this.lastName = lastName;
}
public String getFirstName() {
return firstName;
}
public String getLastName() {
return lastName;
}
}
import org.json.*;
import java.util.*;
class Test {
public static void main(String [] args) throws Exception {
User user = new User("Jon", "Skeet");
JSONObject single = new JSONObject(user);
System.out.println("Single user: " + single);
Set<User> users = new HashSet<>();
users.add(new User("Jon", "Skeet"));
users.add(new User("Holly", "Skeet"));
JSONObject multiple = new JSONObject();
multiple.put("users", users);
System.out.println("Multiple users: " + multiple);
}
}
Output:
Single user: {"lastName":"Skeet","firstName":"Jon"}
Multiple users: {"users":[{"lastName":"Skeet","firstName":"Holly"},{"lastName":"Skeet","firstName":"Jon"}]}
I got correct result using the code below. Can you highlight if you are doing something different? Maybe I can make similar changes and try once.
public static void main(String[] args){
HashSet<String> users = new HashSet<>();
users.add("user1");
users.add("user2");
JSONObject j = new JSONObject();
j.put("users", users);
System.out.println(j.toString(2));
}
Output:
{"users": [ "user2", "user1" ]}
================================== EDIT =================================
I think I figured what the problem was. Please try the following code and let us know if that worked.
public static void main(String[] args) {
JSONObject o1 = new JSONObject();
o1.put("1", new User("User1"));
JSONObject o2 = new JSONObject();
o2.put("2", new User("User2"));
HashSet<JSONObject> users = new HashSet<>();
users.add(o1);
users.add(o2);
JSONObject j = new JSONObject();
j.put("users", users);
System.out.println(j.toString(2));
}
Using gson, it is much simpler.
Use the following code snippet:
// create a new Gson object
Gson gson = new Gson();
// convert your set to json
String jsonUsersSet = gson.toJson(users);
// print your generated json
System.out.println("jsonUsersSet: " + jsonUsersSet);
Convert from JSON string to your Java object:
// Converts JSON string into a set of user object
Type type = new TypeToken<Set<User>>(){}.getType();
Set<User> userSet = gson.fromJson(jsonUsersSet, type);
// print your Set<User>
System.out.println("userSet : " + userSet);

Jackson JSON + Java Generics

I am trying to deserialize/map the below JSON to List<Bill> java object using Jackson json library. (this json was generated by jackson, Iam omitting that piece for brevity)
{"bills":[{"amount":"13","billId":"billid3"}]}
Here is my conversion method:
private static void convert(){
String jsonBill = "{\"bills\":[{\"amount\":\"13\",\"billId\":\"billid3\"}]}";
ObjectMapper mapper = new ObjectMapper();
List<Bill> bills = null;
try {
bills = mapper.readValue(jsonBill, new TypeReference<List<Bill>>() { });
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("bills = " + bills.size());
}
The Bill entity is below:
#JsonTypeInfo(use=JsonTypeInfo.Id.CLASS)
public class Bill {
private String amount;
private String billId;
public String getBillId() {
return billId;
}
public void setBillId(String billId) {
this.billId = billId;
}
public String getAmount() {
return amount;
}
public void setAmount(String amount) {
this.amount = amount;
}
}
and I get this error:
**org.codehaus.jackson.map.JsonMappingException: Can not deserialize instance of java.util.List out of START_OBJECT token
at [Source: java.io.StringReader#7a84e4; line: 1, column: 1]**
at org.codehaus.jackson.map.JsonMappingException.from(JsonMappingException.java:160)
at org.codehaus.jackson.map.deser.StdDeserializationContext.mappingException(StdDeserializationContext.java:194)
at org.codehaus.jackson.map.deser.CollectionDeserializer.deserialize(CollectionDeserializer.java:103)
at org.codehaus.jackson.map.deser.CollectionDeserializer.deserialize(CollectionDeserializer.java:93)
at org.codehaus.jackson.map.deser.CollectionDeserializer.deserialize(CollectionDeserializer.java:25)
at org.codehaus.jackson.map.ObjectMapper._readMapAndClose(ObjectMapper.java:1980)
at org.codehaus.jackson.map.ObjectMapper.readValue(ObjectMapper.java:1278)
Here is my simplified spring3 controller which returns the i/p json (with Jackson mapping configured as default view):
#ModelAttribute("bills")
#RequestMapping(value = "/", method = RequestMethod.GET)
public List<Bill> fetchBills() throws IOException {
Bill bill = new Bill();
bill.setAmount("13");
bill.setBillId("billid3");
List<Bill> bills = new ArrayList<Bill>();
bills.add(bill);
return bills;
}
I guess I am missing something obvious.. but not sure what it is.. Any ideas?
The problem lies not in your code, but your example input. What you're actually trying to deserialize is an object with a field named "bills", not a list! What you should be using as input is:
[{"billId":"billid3","amount":"13"}]
This is an array of objects, which is converted to a list.
Try using ObjectWriter instead of ObjectMapper
Writer writer=new StringWriter();
ObjectWriter oWriter=om.writerWithType(new TypeReference<List<Bill>>() {
});
oWriter.writeValue(writer, result);
I'm using jackson 1.9.2

Categories