18

MongoDB seems to return BSON/JSON objects.

I thought that surely you'd be able to retrieve values as Strings, ints etc. which can then be saved as POJO.

I have a DBObject (instantiated as a BasicDBObject) as a result of iterating over a list ... (cur.next()).

Is the only way (other than using some sort of persistence framework) to get the data into a POJO to use a JSON serlialiser/deserialiser?

My method looks like this:

public List<User> findByEmail(String email){
         DBCollection userColl;
         try {
            userColl = Dao.getDB().getCollection("users"); } catch (UnknownHostException e) { e.printStackTrace(); } catch (MongoException e) { e.printStackTrace();}
            DBCursor cur = userColl.find();
            List<User> usersWithMatchEmail = new ArrayList<User>();

            while(cur.hasNext()) {
               // this is where I want to convert cur.next() into a <User> POJO
               usersWithMatchEmail.add(cur.next());
            }
        return null;
    }

EDIT: It's pretty obvious, just do something like this.

Ankur
  • 50,282
  • 110
  • 242
  • 312
  • 1
    Stupid me, you can just call get() on a DBObject and get the value. I'll post the code. – Ankur Oct 07 '11 at 07:39
  • I just want to point out the most recent answer, where a driver-native solution is proposed: https://stackoverflow.com/a/49926224/503900 – bigstones Apr 22 '18 at 10:14

5 Answers5

49

Let Spring do the heavy lifting with the stuff it already has built for this...

The real trick is: mongoTemplate.getConverter().read(Foo.class, obj);

For example, when using a DBCursor -

while (cursor.hasNext()) { 
    DBObject obj = cursor.next(); 
    Foo foo = mongoTemplate.getConverter().read(Foo.class, obj);  
    returnList.add(foo); 
}

http://revelfire.com/spring-data-mongodb-convert-from-raw-query-dbobject/

chris mathias
  • 517
  • 4
  • 4
8

There is a few java libs that can help you with it:

Igor Artamonov
  • 35,450
  • 10
  • 82
  • 113
  • Thanks, for now I'm trying to learn the Java API but will use one of those eventually. – Ankur Oct 07 '11 at 07:39
  • +1 for spring-data-mongodb, its fantastic. Has annotations to specify document ID, field names, doc references; be aware there is no support for cascading saves: http://static.springsource.org/spring-data/data-mongodb/docs/current/reference/html/#mapping-usage-references – Andrew B Mar 01 '12 at 11:17
  • 1
    @AndrewB can Spring data mongodb be used in an EJB project? And is it a wise thing to do? Since rest of my project has no dependency over Spring whatsoever! – Niks Feb 13 '14 at 13:43
6

Though a late answer , someone might find this useful.

I use GSON to convert from BasicDBObject to my own POJO which is TinyBlogDBObject

TinyBlogDBObject obj = convertJSONToPojo(cursor.next().toString());

private static TinyBlogDBObject convertJSONToPojo(String json){

    Type type = new TypeToken< TinyBlogDBObject >(){}.getType();

    return new Gson().fromJson(json, type);

}
Tito
  • 8,894
  • 12
  • 52
  • 86
  • 1
    this doesn't work because of the id returned in the form {"_id":{"$oid":xxxx} and gson complains. You need to manually convert it to a string or replace the value in a jsonobject. – arisalexis Oct 16 '14 at 15:46
  • Or you can supply your own _id values as strings in the first place, and avoid problems like that. – Bob Kerns Nov 30 '14 at 07:55
5

1. Provide MongoDatabase bean with proper CodecRegistry

@Bean
public MongoClient mongoClient() {
    ConnectionString connectionString = new ConnectionString("mongodb://username:password@127.0.0.1:27017/dbname");

    ConnectionPoolSettings connectionPoolSettings = ConnectionPoolSettings.builder()
            .minSize(2)
            .maxSize(20)
            .maxWaitQueueSize(100)
            .maxConnectionIdleTime(60, TimeUnit.SECONDS)
            .maxConnectionLifeTime(300, TimeUnit.SECONDS)
            .build();

    SocketSettings socketSettings = SocketSettings.builder()
            .connectTimeout(5, TimeUnit.SECONDS)
            .readTimeout(5, TimeUnit.SECONDS)
            .build();

    MongoClientSettings clientSettings = MongoClientSettings.builder()
            .applyConnectionString(connectionString)
            .applyToConnectionPoolSettings(builder -> builder.applySettings(connectionPoolSettings))
            .applyToSocketSettings(builder -> builder.applySettings(socketSettings))
            .build();

    return MongoClients.create(clientSettings);
}

@Bean 
public MongoDatabase mongoDatabase(MongoClient mongoClient) {
    CodecRegistry defaultCodecRegistry = MongoClientSettings.getDefaultCodecRegistry();
    CodecRegistry fromProvider = CodecRegistries.fromProviders(PojoCodecProvider.builder().automatic(true).build());
    CodecRegistry pojoCodecRegistry = CodecRegistries.fromRegistries(defaultCodecRegistry, fromProvider);
    return mongoClient.getDatabase("dbname").withCodecRegistry(pojoCodecRegistry);
}

2. Annotate POJOS

public class ProductEntity {

    @BsonProperty("name") public final String name;
    @BsonProperty("description") public final String description;
    @BsonProperty("thumb") public final ThumbEntity thumbEntity;

    @BsonCreator
    public ProductEntity(
            @BsonProperty("name") String name,
            @BsonProperty("description") String description,
            @BsonProperty("thumb") ThumbEntity thumbEntity) {
        this.name = name;
        this.description = description;
        this.thumbEntity = thumbEntity;
    }
}

public class ThumbEntity {

    @BsonProperty("width") public final Integer width;
    @BsonProperty("height") public final Integer height;
    @BsonProperty("url") public final String url;

    @BsonCreator
    public ThumbEntity(
            @BsonProperty("width") Integer width,
            @BsonProperty("height") Integer height,
            @BsonProperty("url") String url) {
        this.width = width;
        this.height = height;
        this.url = url;
    }
}

3. Query mongoDB and obtain POJOS

MongoCollection<Document> collection = mongoDatabase.getCollection("product");
Document query = new Document();
List<ProductEntity> products = collection.find(query, ProductEntity.class).into(new ArrayList<>());

Please check my answer in other post
POJO to org.bson.Document and Vice Versa

kamildab_84
  • 325
  • 4
  • 8
  • How do you handle date/time classes in case of using POJOs? – Maayan Hope Dec 16 '18 at 10:14
  • You do not have to use date/time mongo data type at all. Instead you can use long datatype where you can save current timestamp. There is also second probably even better option that you can get a date from ObjectId. I always use one of these two options (long or object id), I never use date/time mongo data type – kamildab_84 Mar 07 '20 at 06:37
2

You can use GSON library provided by Google. Here is the example of it. There are many other api that you can use to convert json into pojo like jettision api,etc.

Anand Soni
  • 5,070
  • 11
  • 50
  • 101