2014-04-14 122 views
5

新GSON()的toJSON(新的ObjectId())轉換BSON類型的ObjectId以JSON(MongoDB中存儲)-Java

當我做以上,輸出我得到的是

「 _id」:{ 「_time」:1374347520, 「_MACHINE」:-1025067326, 「_inc」:585905201, 「_new」:假}

但實際上我想這是因爲

「_id」:{ 「$ OID」:51eae100c2e6b6c222ec3431}

這是通常的mongodb的ID的格式。 Java中的這個更好的方法是什麼?

更新:

我的值對象

import com.google.gson.annotations.SerializedName; 
import org.bson.types.ObjectId; 

public class TaskObject { 

    @SerializedName("_id") 
    private ObjectId _id; 

    @SerializedName("revNo") 
    private int revNo; 
} 

我想這個存儲使用自定義到MongoDB的_id

TaskObject taskObject = new TaskObject(); 
taskObject.set_id(new ObjectId()); 
TaskMongoDBClient.getInstance(). 
     persistNewTaskData(new Gson().toJson(taskObject)); 

什麼是存儲在MongoDB中看起來是這樣的。

_id:{ 「_time」:1397464341, 「_MACHINE」:1441187434, 「_inc」:-1687457948, 「_new」:真正}

相反_id的:{ 「$ OID」: xxxx},我可以通過使用oid值進行查詢。

我在做什麼錯在這裏?請幫忙。

謝謝

+0

我添加了更多細節。 –

+0

你的意思是你想在Json –

+0

中添加新的屬性$ oid。很抱歉,現在我找不到更好的方式來解釋我的問題了。如果您有任何人在這種情況下,請告訴我您的方法是什麼,或者什麼是與BSON數據類型更兼容的庫。 –

回答

9

有至少兩種可能的方式來做到這一點。可能最正確的方法是使用GSON TypeAdapter來配置ObjectId如何寫入(並從中讀取)JSON。你需要創建一個實現TypeAdapter的東西,並將其註冊到GsonBuilder,這樣GSON知道有一種處理ObjectIds的特殊方法。

我寫了一個小測試,以證明其工作原理,使用您的使用案例和實例對象(但略去了該領域revNo):

@Test 
public void shouldWriteCorrectJSON() { 
    // given 
    TaskObject taskObject = new TaskObject(); 
    taskObject._id = new ObjectId("51eae100c2e6b6c222ec3431"); 

    Gson gson = new GsonBuilder().registerTypeAdapter(ObjectId.class, new ObjectIdTypeAdapter()).create(); 

    // when 
    String gsonString = gson.toJson(taskObject); 

    // then 
    assertThat(gsonString, is("{\"_id\":{\"$oid\":\"51eae100c2e6b6c222ec3431\"}}")); 
} 

private class ObjectIdTypeAdapter extends TypeAdapter<ObjectId> { 
    @Override 
    public void write(final JsonWriter out, final ObjectId value) throws IOException { 
     out.beginObject() 
      .name("$oid") 
      .value(value.toString()) 
      .endObject(); 
    } 

    @Override 
    public ObjectId read(final JsonReader in) throws IOException { 
     in.beginObject(); 
     assert "$oid".equals(in.nextName()); 
     String objectId = in.nextString(); 
     in.endObject(); 
     return new ObjectId(objectId); 
    } 
} 

注意,測試斷言JSON的樣子你需要它,並且我必須創建一個ObjectIdTypeAdapter,它知道ObjectId的字段名稱是「$ oid」,並且該值只是ObjectID的字符串值,並且不會單獨對所有字段進行序列化。

另請注意,如果您更改對象寫入JSON的方式,則還需要更改其讀取方式。所以我也實現了read來檢查字段名稱是否正確(如果不正確,你應該在這裏拋出一個異常,而不是使用簡單的斷言),然後讀取值並從該字符串值創建ObjectId 。

在現實生活中,您可能還希望在這兩種情況下檢查空值。

因爲我是一個負責任的編碼器,我也寫了一個測試,以顯示讀數的情況下也工作:

@Test 
public void shouldReadFromJSON() { 
    // given 
    Gson gson = new GsonBuilder().registerTypeAdapter(ObjectId.class, new ObjectIdTypeAdapter()).create(); 

    // when 
    TaskObject actualTaskObject = gson.fromJson("{\"_id\":{\"$oid\":\"51eae100c2e6b6c222ec3431\"}}", TaskObject.class); 

    // then 
    TaskObject taskObject = new TaskObject(); 
    taskObject._id = new ObjectId("51eae100c2e6b6c222ec3431"); 
    assertThat(actualTaskObject._id, is(taskObject._id)); 
} 

延伸閱讀:

+0

TypeAdapter似乎提供了格式驗證,這是我的原始問題的正確答案。讓我試試看,並將其標記爲已接受的答案。 無論如何,我所做的是,而不是掛在_id字段(這是Mongo默認格式)中的$ oid子值,我做了以下解決方法。 TaskObject _id已更改字符串類型。 我的任務看起來像這樣。 _id = ObjectId.get()。toString();以「_id:535e3b090557f05f783c2805」格式保存。 –

+0

是的,人們使用字符串來表示ID也很常見 - 可以說這是一個更好的答案,因爲它可以防止Mongo特定的ObjectID類泄漏到您的域對象中。 – Trisha

+0

@Trisha你寫了兩個測試的好東西,但我在seond(讀)一個有問題。我稍微轉換了它(我需要閱讀Long's而不是objectids),但它本質上是一樣的。你能否看到這裏有什麼問題? http://stackoverflow.com/questions/36134737/read-bson-mongodb-into-pojo-using-gson-and-typeadapter –

相關問題