Keep few fields in Json - Java - java

public class User {
String name;
String id;
Address[] address;
....
....
//40 more fields
}
public class Address {
String street;
String city;
String state;
}
I have a List and I need to convert it to json with only few fields.
public String fetchUsers(List<Users> users, List<String> fields) {
//fetch the list of users having the specific fields in the list and return as json
}
fields = ["name", "address.state"]
I can remove fields in json.... But, I need to keep restricted fields as per values passed in the method. I can use any third party lib as well.

Use com.google.gson.Gson library for serialize your objects into json and you have to create ExclusionStrategy for your object for fields which you want to skip or not. create a GsonBuilder object from that and parse your object from it.
this is perfectly working fine.
import com.google.gson.ExclusionStrategy;
import com.google.gson.FieldAttributes;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class ABC {
public class User {
public String name;
public String id;
public Address[] address;
}
public class Address {
public String street;
public String city;
public String state;
}
public static ExclusionStrategy createStrategy(List<String> fields) {
return new ExclusionStrategy() {
public boolean shouldSkipField(FieldAttributes fieldAttributes) {
if (fields.stream().anyMatch(e -> e.equals(fieldAttributes.getName()))) {
return false;
}
return true;
}
public boolean shouldSkipClass(Class aClass) {
return false;
}
};
}
public String fetchUsers(List<User> users, List<String> fields) {
GsonBuilder builder = new GsonBuilder();
builder.setExclusionStrategies(createStrategy(fields));
Gson gson = builder.create();
return gson.toJson(users);
}
public static void main(String[] args) {
ABC x = new ABC();
Address add = x.new Address();
add.city = "city";
add.state = "state";
add.street = "street";
Address[] array = new Address[1];
array[0] = add;
User user = x.new User();
user.address = array;
user.id = "id";
user.name = "name";
List<User> users = new ArrayList<>();
users.add(user);
List<String> fields = Arrays.asList("name", "address", "state");
String json = x.fetchUsers(users, fields);
System.out.println(json);
}
}
and output of this code is :
[{"name":"name","address":[{"state":"state"}]}]
and dependency for Gson is.
<!-- https://mvnrepository.com/artifact/com.google.code.gson/gson -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.5</version>
</dependency>

Related

How to keep the JSON's order preserved while sending to frontend application from SpringBoot Application's service?

I'm developing a springboot application.
I've a class with the following fields
class MyClass
{
String s1;
String s2;
String s3;
String s4;
//getters setters constructors
}
I'm calling an API which in turn calls a service.
public String myService()
{
JSONArray arr1 = new JSONArray();
for (Items item : itemsList)
{
JSONObject itemObj = new JSONObject();
itemObj.put("s1","Value1");
itemObj.put("s2","Value2");
itemObj.put("s3","Value3")
itemObj.put("s4","Value4");
arr1.put(itemObj);
}
JSONObject out = new JSONObject();
out.put("total_Items", arr1);
return out.toString(); // this is org.json.JSONObject
}
This way I'm able to get the excel with the reordered members as the columns when a button is clicked at the frontend angular app.
What I want is the order of the the members in the columns remains preserved when exporting into an excel sheet.
s1|s2|s3|s4 //as per the above example
I've many other services as well, which return different types of Objects(apart from the MyClass mentioned here) so I wanted to return the elements in the order defined (as per the order of members in the class) from the backend itself.
I know that JSON does not allow us to preserve the order as it internally uses a HASHMAP.
Is there a way to return a JSON response such that the order remains same as that of the class members?
I also tried using GSON in the below way.
public String myService()
{
MyClass itemsArray[] = new MyClass[itemsList.size()];
int i=0;
for (Items item : itemsList)
{
MyClass itemObj = new MyClass();
itemObj.setS1("Value1");
itemObj.setS2("Value2");
itemObj.setS3("Value3")
itemObj.setS4("Value4");
itemsArray[i]=itemObj;
}
Gson gson = new Gson();
return gson.toJson(itemsArray); // this is java.lang.String
}
In this scenario I'm able to get the API response(on POSTMAN) with the elements in ordered fashion but when exporting on the frontend angular app it freezes at the downloading screen.
I tried doing conversion to JSONObject and other things randomly but was not able to make the code work properly.
Is there anyway the problem can be resolved at the backend...or something needs to be done at the frontend only?
Thanks in advance.
If you want to do using DataStructure use LinkedHashMap as given below. It will serialize in inserted order.
public static void main(String args[]){
ObjectMapper mapper = new ObjectMapper();
Map<String, String> itemObj = new LinkedHashMap<>();
itemObj.put("s91","Value1");
itemObj.put("s2","Value2");
itemObj.put("s3","Value3");
itemObj.put("s4","Value4");
try {
String jsonString = mapper
.writerWithDefaultPrettyPrinter()
.writeValueAsString(itemObj);
System.out.println(jsonString);
}
catch (IOException e) {
e.printStackTrace();
}
}
{
"s91" : "Value1",
"s2" : "Value2",
"s3" : "Value3",
"s4" : "Value4"
}
If you want to serialize in sorted order the use TreeMap, it will serialize in sorted key
Map<String, String> itemObj = new TreeMap<>();
...
{
"s2" : "Value2",
"s3" : "Value3",
"s4" : "Value4",
"s91" : "Value1"
}
This can be done using Jackson library using the #JsonPropertyOrder annotation.
You can define the order of elements as given below above class
#JsonPropertyOrder({ "s3", "s2", "s1", "s4"})
Refer to below a working example
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sun.istack.NotNull;
import java.io.IOException;
import java.util.UUID;
#JsonPropertyOrder({ "id", "password", "name", "email", "enabled" })
public class UserResource {
private UUID id;
#NotNull
private String name;
#NotNull
private String email;
private boolean enabled;
private String password;
public UserResource(UUID id, String name, String email, boolean enabled, String password) {
this.id = id;
this.name = name;
this.email = email;
this.enabled = enabled;
this.password = password;
}
public UUID getId() {
return id;
}
public void setId(UUID id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public static void main(String args[]){
ObjectMapper mapper = new ObjectMapper();
try {
UserResource student = new UserResource(UUID.randomUUID(), "sheel", "sheel#c4c.com",true, "$$$$$$%%##^^$DSGHHH");
String jsonString = mapper
.writerWithDefaultPrettyPrinter()
.writeValueAsString(student);
System.out.println(jsonString);
}
catch (IOException e) {
e.printStackTrace();
}
}
}
and output as given below
{
"id" : "fbfcd21d-731e-4acb-9fec-90a499e47cc9",
"password" : "$$$$$$%%##^^$DSGHHH",
"name" : "sheel",
"email" : "sheel#c4c.com",
"enabled" : true
}

How to get the name of an Attribute from an Entity

I have the following entity class:
public class Conversation {
private String id;
private String ownerId;
private Long creationDate;
public Conversation(String id, String ownerId, Long creationDate){
this.id = id;
this.ownerId = ownerId;
this.creationDate = creationDate;
}
}
On other submodule through an external service, on each insertion, I recive a map of the following entities:
public class AttributeValue {
private Sring s; //string attribute
private String n; //number attribute
public String getS() {
return this.s;
}
public String getN() {
return this.n;
}
public AttributeValue(String s, String n){
this.s = s;
this.n = n;
}
}
//Example if I insert this conversation: new Conversation("1", "2", 1623221757971)
// I recive this map:
Map<String, AttributeValue> insertStream = Map.ofEntries(
entry("id", new AttributeValue("1", null)),
entry("ownerId", new AttributeValue("2", null)),
entry("creationDate", new AttributeValue(null, "1623221757971"))
);
To read the ownerId field from the map, I have to do this:
String ownerId = insertStream.get("ownerId").getS();
My question is, instead of have to write: insertStream.get("ownerId"), exists any way through Reflection to read the name of the field from the entity (Conversation.ownerId)?
This is because we want to mantain the submodule and If we make a change on the entitity, for example change ownerId for ownerIdentifier, the submodule shows a compilation error or is changed automatically.
Is this what you want? Field#getName()
Example code:
Field[] conversationFields = Conversation.class.getDeclaredFields();
String field0Name = conversationFields[0].getName();
Depending on the JVM used, field0Name can be "id". You can also use Class#getFields(), this method includes all Fields that are accessible in this class (super class's fields).
Another option (not using reflection) would be to refactor your code.
import java.util.Map;
import java.util.HashMap;
public class Conversation {
public static String[] names = {
"id", "ownerId", "creationDate"
};
private Map<String, Object> data = new HashMap<String,Object>();
public Conversation(Object... data) {
if(data.length!=names.length)
throw new IllegalArgumentException("You need to pass "+names.length+" arguments!");
for(int i=0; i<names.length; i++)
data.put(names[i],data[i]);
}
public Map<String,Object> getData() { return data; }
// You can pass "id"/"ownerId" or names[0]/names[1]
public String getString(String key) {
return (String)data.get(key);
}
// You can pass "creationDate" or names[2]
public long getLong(String key) {
return (long)data.get(key);
}
}
You could then create Conversation Objects like before:
Conversation c = new Conversation("myId","myOwnerId",123456789L);
You could also add public static String fields like ID="id", but changing the value of a field will never change the field's name.

How to return only one specific null field with GSON?

If I have a simple object as follows:
String name;
String email;
int age;
boolean isDeveloper;
Then let's say JSON object received have values:
{"name":null,"email":null,"age":26,"isDeveloper":true}
When deserializing this JSON using GSON as default I have:
{"age":26,"isDeveloper":true}
But email field missing will cause a failure afterwards on my application so I want to add
email = null;
Serialize back to JSON and have only this field value as null. Also not ignoring any non null fields.
Other null values should not be added to the resulting JSON.
I tried deserializing with a default GSON builder then serializing with a GSON that allows null values as:
Gson gson = new GsonBuilder().serializeNulls().create();
Problem is: this will look all null/empty values from the object class and set them all
{"name":null,"email":null,"age":26,"isDeveloper":true}
How can I set email property null then serialize back to a JSON containing only this field as null without ignoring any other non null values?
I'm using gson v2.2.4
Here is example code:
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
public class App
{
private class UserSimple {
public String name;
public String email;
public int age;
public boolean isDeveloper;
UserSimple(String name, String email, int age, boolean isDeveloper) {
this.name = name;
this.email = email;
this.age = age;
this.isDeveloper = isDeveloper;
}
}
public static void main( String[] args )
{
String userJson = "{'age':26,'email':'abc#dfg.gh','isDeveloper':true,'name':null}";
Gson gson = new GsonBuilder()
.setPrettyPrinting()
.disableHtmlEscaping()
.create();
Gson gsonBuilder = new GsonBuilder().serializeNulls().create();
UserSimple deserializedObj = gson.fromJson(userJson, UserSimple.class);
System.out.println("\n"+gson.toJson(deserializedObj));
deserializedObj.email = null;
String serializedObj = gsonBuilder.toJson(deserializedObj, UserSimple.class);
System.out.println("\n"+serializedObj);
}
}
You could create your own custom adapter to resolve the issue at hand :
class MyCustomTypeAdapter extends TypeAdapter<UserSimple> {
#Override
public void write(JsonWriter writer, UserSimple userSimple) throws IOException {
writer.beginObject();
if(userSimple.getName() != null){
writer.name("name");
writer.value(userSimple.getName());
}
// you want to include email even if it's null
writer.name("email");
writer.value(userSimple.getEmail());
if(userSimple.getAge() != null){
writer.name("age");
writer.value(userSimple.getAge());
}
if(userSimple.getDeveloper() != null){
writer.name("isDeveloper");
writer.value(userSimple.getDeveloper());
}
writer.endObject();
}
public UserSimple read(JsonReader reader) throws IOException {
// you could create your own
return null;
}
}
Input :
String userJson = "{'age':null,'email':null,'isDeveloper':true,'name':'somename'}";
Output :
serializedObj :{"name":"somename","email":null,"isDeveloper":true}
Input :
String userJson = "{'age':20,'email':null,'isDeveloper':true,'name':'somename'}";
Output :
serializedObj :{"name":"somename","email":null,"age":20,"isDeveloper":true}
Have a look at https://google.github.io/gson/apidocs/com/google/gson/TypeAdapter.html
Have you considered using jackson? I think it's more powerful and faster than Gson. But that's just my opinion, I don't mean to offend anyone. I've also run into situations where jackson could do something that gson couldn't.
Here's the code that does the job for you:
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
public class Main {
static class Person {
#JsonInclude(JsonInclude.Include.ALWAYS)
private String name;
#JsonInclude(JsonInclude.Include.NON_NULL)
private String email;
#JsonInclude(JsonInclude.Include.NON_NULL)
private Integer age;
public Person(String name, String email, Integer age) {
this.name = name;
this.email = email;
this.age = age;
}
public String getName() {
return name;
}
public String getEmail() {
return email;
}
public Integer getAge() {
return age;
}
}
public static void main(String[] args) throws Exception {
ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter(); // pretty printing only enabled for demonstration purposes
String test = ow.writeValueAsString(new Person(null, null, 2));
System.out.println(test);
}
}
output is:
{
"name" : null,
"age" : 2
}
name is also output because the inclusion policy for it is JsonInclude.Include.ALWAYS.
In maven dependencies include:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.6</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.6</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.6</version>
</dependency>
There's also this answer: Gson serialize null for specific class or field but it looks like it's not very good.

Parsing JSON data into model objects in Java

I haven't worked with JSON data before, thus the question.
I've the following JSON object in a file.
{
"courses": [
{ "id":998", "name":"Java Data Structures", "teacherId":"375" },
{ "id":"999", "name":"Java Generics", "teacherId":"376" }
],
"teachers": [
{ "id":"375", "firstName":"Amiyo", "lastName":"Bagchi"},
{ "id":"376", "firstName":"Dennis", "lastName":"Ritchie"}
]
}
Here are my model Objects.
public class Course {
private int _id;
private String _name;
private Teacher _teacher;
}
public class Teacher {
private int _id;
private String _firstName;
private String _lastName;
}
My task is to read the JSON Objects and return a list of Model objects.
I've imported the simple.JSON family of jar and here's my code that reads the file.
FileReader reader = new FileReader(path);
JSONParser parser = new JSONParser();
Object obj = parser.parse(reader);
JSONObject jsonObject = (JSONObject) obj;
My question is,
How do I parse the JSON document into my Model objects?
If the input file is JSON but of a different format how do I throw exception/handle the anomaly?
Any help appreciated.
UPDATE I suggest you use JSON parser to parse the data:
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.List;
import java.util.HashMap;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
class Course {
public int _id;
public String _name;
public Teacher _teacher;
private Course(int id, String name, Teacher teacher){
this._id = id;
this._name = name;
this._teacher = teacher;
}
public Course() {
}
}
class Teacher {
public int _id;
public String _firstName;
public String _lastName;
private Teacher(int id, String fname, String lname){
this._id = id;
this._firstName = fname;
this._lastName = lname;
}
public Teacher(){
}
}
public class jsontest {
public static void main(String[] args) throws JSONException, IOException {
// String JSON_DATA = "{\n"+
// " \"courses\": [\n"+
// " { \"id\":\"998\", \"name\":\"Java Data Structures\", \"teacherId\":\"375\" },\n"+
// " { \"id\":\"999\", \"name\":\"Java Generics\", \"teacherId\":\"376\" }\n"+
// "\n"+
// " ],\n"+
// " \"teachers\": [\n"+
// " { \"id\":\"375\", \"firstName\":\"Amiyo\", \"lastName\":\"Bagchi\"},\n"+
// " { \"id\":\"376\", \"firstName\":\"Dennis\", \"lastName\":\"Ritchie\"} \n"+
// " ]\n"+
// "}\n"+
// "";
// read json file into string
String JSON_DATA = new String(Files.readAllBytes(Paths.get("path_to_json_file")), StandardCharsets.UTF_8);
// using a JSON parser
JSONObject obj = new JSONObject(JSON_DATA);
// parse "teachers" first
List<Teacher> listCourses = new ArrayList<Teacher>();
List<JSONObject> listObjs = parseJsonData(obj,"teachers");
for (JSONObject c: listObjs) {
Teacher teacher = new Teacher();
teacher._id = c.getInt("id");
teacher._firstName = c.getString("firstName");
teacher._lastName = c.getString("lastName");
listCourses.add(teacher);
}
// parse "courses" next
List<Course> resultCourses = new ArrayList<Course>();
List<JSONObject> listObjs2 = parseJsonData(obj, "courses");
for (JSONObject c: listObjs2) {
Course course = new Course();
course._id = c.getInt("id");
course._name = c.getString("name");
int teacherId = c.getInt("teacherId");
HashMap<String, Teacher> map = new HashMap<String, Teacher>();
for (Teacher t: listCourses){
map.put(Integer.toString(t._id), t);
}
course._teacher = map.get(Integer.toString(teacherId));
resultCourses.add(course);
}
}
public static List<JSONObject> parseJsonData(JSONObject obj, String pattern)throws JSONException {
List<JSONObject> listObjs = new ArrayList<JSONObject>();
JSONArray geodata = obj.getJSONArray (pattern);
for (int i = 0; i < geodata.length(); ++i) {
final JSONObject site = geodata.getJSONObject(i);
listObjs.add(site);
}
return listObjs;
}
}
Output:
BTW: The json data in the example has one value whose double quotes are not in pairs. To proceed, it must be fixed.
You should try using Jackson as the JSON parsing library instead. There is a lot more support and features that come with it.
In your case, a couple of annotations to map the JSON properties to the Java fields should be sufficient.
https://github.com/FasterXML/jackson-annotations
https://github.com/FasterXML/jackson-databind
UPDATE: Some code, to show just much better this can be done with Jackson.
public class Course {
#JsonProperty("id")
private int _id;
#JsonProperty("name")
private String _name;
#JsonProperty("teacher")
private Teacher _teacher;
// ...public getters and setters
}
public class Teacher {
#JsonProperty("id")
private int _id;
#JsonProperty("firstName")
private String _firstName;
#JsonProperty("lastName")
private String _lastName;
// ...public getters and setters
}
// Container class to conform to JSON structure
public class CoursesDto {
private List<Teacher> teachers;
private List<Course> courses;
}
// In your parser place
ObjectMapper mapper = new ObjectMapper();
FileReader reader = new FileReader(path);
CoursesDto dto = mapper.readValue(reader, CoursesDto.class);
The #JsonProperty annotations tell Jackson what JSON key should be used to deserialize. They are not necessary if the property names match the JSON keys. That means that if you remove the leading underscore from your property names, this would work without annotations. Also, Jackson will default to using public fields and getter/setter methods. This means that you can keep your fields prefixed by _ as long as the getter/setter don't have it (setFirstName(String firstName)).

Inserting Java Object to MongoDB Collection Using Java

I am trying to insert a whole Java object into a MongoDB Collection using Java. I am getting following error:
Error :
Exception in thread "main" java.lang.IllegalArgumentException: can't serialize class net.yogesh.test.Employee
at org.bson.BSONEncoder._putObjectField(BSONEncoder.java:185)
at org.bson.BSONEncoder.putObject(BSONEncoder.java:119)
at org.bson.BSONEncoder.putObject(BSONEncoder.java:65)
at com.mongodb.DBApiLayer$MyCollection.insert(DBApiLayer.java:176)
at com.mongodb.DBApiLayer$MyCollection.insert(DBApiLayer.java:134)
at com.mongodb.DBApiLayer$MyCollection.insert(DBApiLayer.java:129)
at com.mongodb.DBCollection.save(DBCollection.java:418)
at net.yogesh.test.test.main(test.java:31)
Emplyoee.java (POJO)
package net.yogesh.test;
import java.io.Serializable;
public class Employee implements Serializable {
private static final long serialVersionUID = 1L;
private long no;
private String name;
public Employee() {
}
public long getNo() {
return no;
}
public void setNo(long no) {
this.no = no;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
Main Method Class (test.java)
package net.yogesh.test;
import java.net.UnknownHostException;
import com.mongodb.BasicDBObject;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.Mongo;
import com.mongodb.MongoException;
public class test {
public static void main(String[] args) throws UnknownHostException,
MongoException {
Mongo mongo = new Mongo("localhost", 27017);
DB db = mongo.getDB("test");
Employee employee = new Employee();
employee.setNo(1L);
employee.setName("yogesh");
BasicDBObject basicDBObject = new BasicDBObject("Name", employee);
DBCollection dbCollection = db.getCollection("NameColl");
dbCollection.save(basicDBObject);
}
}
Can anybody explain why I am getting this error?
I'm a little confused as to know why you'd think this would work in the first place. The first thing you need to know is how to map your POJO to a MongoDB document. Currently, you're not telling the system(your code) how to do that.
You can either use a mapping library for this (Morphia comes to mind) or use ReflectionDBObject. Either solution allows you to map POJO to MongoDB document or MongoDB document to POJO(the former way is a lot more nicely than the latter).
DB db = mongoClient.getDB( "mydb" );
coll = db.getCollection("testCollection");
Employee emp = new Employee();
emp.setId("1001");
emp.setName("John Doe");
//Converting a custom Class(Employee) to BasicDBObject
Gson gson = new Gson();
BasicDBObject obj = (BasicDBObject)JSON.parse(gson.toJson(emp));
coll.insert(obj);
findEmployee(new BasicDBObject("id","1001"));
public static void findEmployee(BasicDBObject query){
DBCursor cursor = coll.find(query);
try {
while(cursor.hasNext()) {
DBObject dbobj = cursor.next();
//Converting BasicDBObject to a custom Class(Employee)
Employee emp = (new Gson()).fromJson(dbobj.toString(), Employee.class);
System.out.println(emp.getName());
}
} finally {
cursor.close();
}
}
I thought that it would be useful to post code that did conversions both ways.
Storing an Employee Object
Finding and re-creating an employee Object
Hope this is useful..
Pro
you continue to work with strong typed objects as you wanted to
Contra
Some people really dislike : extends
package foo;
import com.mongodb.BasicDBObject;
public class Employee extends BasicDBObject {
private static final long serialVersionUID = 2105061907470199595L;
//should be something shorter as "name" like "n"
//here just use name to conform your sample
public static final String NAME = "name";
public static final String NO = "no";
public static final String COLLECTION_NAME = "employee";
public Long getNo() {
return getLong(NO);
}
public void setNo(long no) {
put(NO, no);
}
public String getName() {
return getString(NAME);
}
public void setName(String name) {
put(NAME, name);
}
}
package foo;
import java.net.UnknownHostException;
import com.mongodb.DB;
import com.mongodb.DBCollection;
import com.mongodb.Mongo;
import com.mongodb.MongoException;
public class Test {
public static void main(String[] args) throws UnknownHostException,
MongoException {
Mongo mongo = new Mongo("localhost", 27017);
DB db = mongo.getDB("yeahMongo");
Employee employee = new Employee();
employee.setNo(1L);
employee.setName("yogesh");
DBCollection employeeCollection = null ;
employeeCollection = db.getCollection(Employee.COLLECTION_NAME);
employeeCollection.save(employee);
System.err.println(employeeCollection.findOne());
}
}
In addition to morphia you should take a look to
jongo :
http://jongo.org/
jongo use the same form syntax as js mongo engine, and I found it great point for a beginner. You don't have to switch your mental map between mongojs and java. you can use the js sample with little changes.
You can convert your java object into json string using the gson library and then insert it in mongodb.
Eg:
Gson gson = new Gson();
String json = gson.toJson(Employee);
BasicDBObject basicDBObject = new BasicDBObject("Name", json );
DBCollection dbCollection = db.getCollection("NameColl");
dbCollection.save(basicDBObject);
There have been several changes since this question was asked. Using test.java in the question, here is what worked for me using Google's Gson:
import com.google.gson.Gson;
import com.mongodb.Block;
import com.mongodb.MongoClient;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoDatabase;
import org.bson.Document;
public class test {
public static void main(String[] args) {
MongoClient mongoClient = new MongoClient(); // Connect with default settings i.e. localhost:27017
MongoDatabase db = mongoClient.getDatabase("test"); // Get database "test". Creates one if it doesn't exist
Employee employee = new Employee(); // Create java object
employee.setNo(1L);
employee.setName("yogesh");
// Deserialize object to json string
Gson gson = new Gson();
String json = gson.toJson(employee);
// Parse to bson document and insert
Document doc = Document.parse(json);
db.getCollection("NameColl").insertOne(doc);
// Retrieve to ensure object was inserted
FindIterable<Document> iterable = db.getCollection("NameColl").find();
iterable.forEach(new Block<Document>() {
#Override
public void apply(final Document document) {
System.out.println(document); // See below to convert document back to Employee
}
});
}
}
You can also use Gson to convert retrieved bson document back to Java object:
Gson gson = new Gson();
Employee emp = gson.fromJson(document.toJson(), Employee.class);
With MongoDB you cannot insert your Java bean in the DB, but you have to remap them to MongoDB Object.
In your case you have to do:
BasicDBObject basicDBObject = new BasicDBObject();
basicDBObject.put("no", employee.getNo());
basicDBObject.put("name", employee.getName());
Hopefully this will work for you and you can get help from it.
I performed database operations(insert,delete, update, get, getall) and used Person object for operations in MongoDB with java for demo purpose.
Database connection class
Connection.java
package test;
import org.bson.codecs.configuration.CodecRegistry;
import org.bson.codecs.pojo.PojoCodecProvider;
import static org.bson.codecs.configuration.CodecRegistries.fromProviders;
import static org.bson.codecs.configuration.CodecRegistries.fromRegistries;
import com.mongodb.MongoClient;
import com.mongodb.MongoClientOptions;
import com.mongodb.client.MongoDatabase;
public class Connection {
public MongoClient mongo;
private String db;
public MongoDatabase database;
private static Connection instance;
private Connection() {
db = "chatsystem";
CodecRegistry pojoCodecRegistry = fromRegistries(MongoClient.getDefaultCodecRegistry(),
fromProviders(PojoCodecProvider.builder().automatic(true).build()));
mongo = new MongoClient("localhost", MongoClientOptions.builder().codecRegistry(pojoCodecRegistry).build());
database = mongo.getDatabase(db);
}
public static Connection getInstance() {
if (instance == null) {
instance = new Connection();
return instance;
} else {
return instance;
}
}
}
Model Class
Person.java
package test;
import org.bson.types.ObjectId;
public class Person {
public Person() {
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getFname() {
return fname;
}
public void setFname(String fname) {
this.fname = fname;
}
public String getLname() {
return lname;
}
public void setLname(String lname) {
this.lname = lname;
}
private ObjectId id;
public Person(String username, String email, String password, String fname, String lname) {
super();
this.username = username;
this.email = email;
this.password = password;
this.fname = fname;
this.lname = lname;
}
public ObjectId getId() {
return id;
}
public void setId(ObjectId id) {
this.id = id;
}
private String username;
private String email;
private String password;
private String fname;
private String lname;
}
Main class
test.java
package test;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import static com.mongodb.client.model.Filters.*;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
public class test {
private MongoCollection<Person> person;
Connection conn;
public void getCollection() {
conn = Connection.getInstance();
person = conn.database.getCollection("person", Person.class);
}
public static void main(String[] args) throws Exception {
test t = new test();
t.getCollection();
Person p = new Person();
p.setEmail("test#test.com");
p.setFname("ftest");
p.setLname("ltest");
p.setPassword("testtest");
p.setUsername("test123");
// insert person type objects in database
t.insertPerson(p);
// get all persons from database
List<Person> pp = t.getAllPersons();
Person pt = pp.get(0);
System.out.println(pt.getEmail());
System.out.println(pt.getId());
// get one person from database by username filter
// pass username of person in method argument
Person ph = t.getOnePerson("test123");
System.out.println(ph.getEmail());
System.out.println(ph.getId());
// update/edit person by username filter
// pass username of person in method argument
t.updatePerson("test123");
// delete person by username filter
// pass username of person in method argument
t.removePerson("updatetest123");
}
public void insertPerson(Person p) {
person.insertOne(p);
}
public List<Person> getAllPersons() {
FindIterable<Person> iterable = person.find();
Iterator it = iterable.iterator();
List<Person> allPersons = new ArrayList<>();
while (it.hasNext()) {
Person per = (Person) it.next();
allPersons.add(per);
}
return allPersons;
}
public Person getOnePerson(String username) {
return person.find(eq("username", username)).first();
}
public void updatePerson(String username) {
Person p = new Person();
p.setEmail("update#test.com");
p.setFname("updateftest");
p.setLname("updateltest");
p.setPassword("updatetesttest");
p.setUsername("updatetest123");
person.replaceOne(eq("username", username), p);
}
public void removePerson(String username) {
person.deleteOne(eq("username", username));
}
}
Highly recommend MongoJack, a decent library to map Java objects to/from MongoDB documents.
The code would be something like below:
import java.util.Arrays;
import org.mongojack.JacksonDBCollection;
import com.mongodb.DB;
import com.mongodb.MongoClient;
import com.mongodb.ServerAddress;
public class Test {
public static void main(String[] args) {
MongoClient mongoClient = new MongoClient(Arrays.asList(new ServerAddress("localhost", 27017)));
DB db = mongoClient.getDB("test");
Employee employee = new Employee();
employee.setNo(1L);
employee.setName("yogesh");
JacksonDBCollection<Employee, String> collectionData = JacksonDBCollection.wrap(db.getCollection("NameColl"), Employee.class, String.class);
collectionData.save(employee);
mongoClient.close();
}
}
(PS: Currently I'm using mongo-java-driver v3.2.2, and mongojack v2.6.1)
Use BasicDBObjectBuilder to convert your POJO to an instance of DBObject which a DBCollection can save:
import com.mongodb.BasicDBObjectBuilder;
import com.mongodb.DBObject;
public class Employee {
private long no;
private String name;
// Getters and Setters
public DBObject toDBObject() {
BasicDBObjectBuilder builder = BasicDBObjectBuilder
.start("no", no)
.append("name", name);
return builder.get();
}
}
In order to save, just call toDBObject() on POJO instance and provide it to collection:
public class test {
public static void main(String[] args) throws UnknownHostException,
MongoException {
...
DBCollection dbCollection = db.getCollection("NameColl");
Employee employee = new Employee();
employee.setNo(1L);
employee.setName("yogesh");
dbCollection.save(employee.toDBObject());
}
}
Using this approach:
You don't need to manually create a DBObject every time
You don't need to mess up your POJO by extending Mongo classes (what if your POJO is already extending a class?)
You don't need a Json mapper [and its annotations on POJO fields]
You only have dependency to java-mongo-driver jar
I have the same error, when I try to insert a java BasicDBObject into a MongoDb Collection.
My object is created from a Xml converted to Json.
java.lang.IllegalArgumentException: can't serialize class net.sf.json.JSONNull
at org.bson.BasicBSONEncoder._putObjectField(BasicBSONEncoder.java:299)
at org.bson.BasicBSONEncoder.putMap(BasicBSONEncoder.java:339)
at org.bson.BasicBSONEncoder._putObjectField(BasicBSONEncoder.java:261)
This error is caused by empty tags in Xml; when I removed all empty tags, then I solved it.
Just use "insertOne" method, not save.
MongoCollection collection;
String collectionName = "somename";
String jsonObject = "{}";
if (!mongoTemplate.collectionExists(collectionName)) {
collection = mongoTemplate.createCollection(collectionName);
logger.info("Collection %s was successfully created", collectionName);
} else {
collection = mongoTemplate.getCollection(collectionName);
}
collection.insertOne(Document.parse(jsonObject));
Since nobody has mentioned it - I think there might be a solution to this using bson4jackson. This bills itself as a fast encoder.

Categories

Resources