2017-11-05 7 views
2

MongoDBから特定の形式のデータを読み込むコードがあります。私はそれをテストする必要があります。MongoDB:JSONからLongを読み込もうとするとjava.lang.Integerがjava.lang.Longにキャストできなくなる

そうするためには、私は私がテストしたいデータをJSONを作成します。

{ 
    "id": ObjectId("57552e32e4b0839ede67e0af"), 
    "serial" : 574000690, 
    "startDate" : ISODate("2016-08-22T23:01:56.000Z"), 
    "endDate" : ISODate("2016-10-22T22:01:56.000Z"), 
    "reason": "" 
} 

これが作成されることになったオブジェクトです:

public static class MyObject implements Serializable{ 
    private String id; 
    private long serial; 
    private Date startDate; 
    private Date endDate; 
    private String reason; 
} 

私は、コードを持っていますJSONファイルを読み込んでMongoドキュメントを作成し、DBに書き込みます。

List<Document> docs = dirAsDbObjects(dir + File.separator + 
subDir.getName()).collect(Collectors.toList()); 

docs.forEach(docManipulator); 
docs.forEach(doc -> doc.putIfAbsent("_id", new ObjectId())); 

ret.addAll(docs); 

MongoDatabase db = mongoClient.getDatabase(dbName); 
MongoCollection<Document> coll = db.getCollection(subDir.getName()); 

List<InsertOneModel<Document>> inserts = docs.stream().map(InsertOneModel::new).collect(Collectors.toList()); 
coll.bulkWrite(inserts); 

データが書き込まれるとMongoDBのデータを読み込み、MyObjectインスタンスにそれを移入しようとするコード:

エラーメッセージに失敗し
public MyObject(Document doc) { 
     id = doc.getObjectId(DBConstants.ID).toString(); 
     serial = doc.getLong(DBConstants.SERIAL); 
     startDate = doc.getDate("startDate"); 
     reason = doc.getString("source"); 
    } 

java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.Long 

ためのラインserial = doc.getLong(DBConstants.SERIAL);の。これは基本的に私のJSONから数値を "Integer"として取得し、それを長い間読み取ることができません。

私は次の行を試してみた、それが動作します:

Long.parseLong(doc.get(DBConstants.SERIAL).toString()) 

しかし、それはここに最適なソリューションですか? .toString()はいつも私に数字の文字列表現を与えますか? Longとして読み取ることになるJSONの数値を保持する方法はありますか?

更新:

@glytchingは、優れた答えを与えました!

また、別の方法を発見しました。明らかに、JSONの数値要素をNumberLongにラップすると、Mongoドキュメントから翻訳されたときにはLongと解析されます。

{ 
    "id": ObjectId("57552e32e4b0839ede67e0af"), 
    "serial" : NumberLong(574000690), 
    "startDate" : ISODate("2016-08-22T23:01:56.000Z"), 
    "endDate" : ISODate("2016-10-22T22:01:56.000Z"), 
    "reason": "" 
} 

答えて

2

モンゴJavaドライバがserialの値がそうINT32に「フィット」することができますことを決定しました。だから私は、それはそうのような私のJSONを変更して動作させることができた、古いコードを使用して

それはそのように扱われます。 doc.getLong()を呼び出すと、IntegerをLongにキャストするようにドライバに要求しているため、クラスキャストの例外が発生します。例えば、serialの値が2147483648(すなわち、最大整数値+1)であった場合、Mongo JavaドライバはそれをINT64とみなし、doc.getLong()を安全に呼び出すことができる。だから、

、(a)は、あなたのクラスモデルにLongとして、この属性をモデル化しているとINT64は...あなたがその永続タイプに敏感でなければならないとして、(b)は、この属性のすべての持続値がストレージを必要としないので、それをLongに変換するとき。

どのようにですか?さて、serial属性が何らかの種類の番号(例:INT32INT64)として保持されている限り、この呼び出しは...

doc.get(DBConstants.SERIAL) 

は...常にjava.lang.Numberのいくつかのサブクラスであるため、Numberにキャストし、longValue()を使用して動作するオブジェクトを返します。例えば

serial = ((Number) doc.get(DBConstants.SERIAL)).longValue() 
関連する問題