diff --git a/native/jni/src/suggest/core/dictionary/word_property.cpp b/native/jni/src/suggest/core/dictionary/word_property.cpp
index ed32bde8b3544e3787baa0d7ba25b79ee2ec1d29..4a260a98288faa35c688e7671c9918a631beec6c 100644
--- a/native/jni/src/suggest/core/dictionary/word_property.cpp
+++ b/native/jni/src/suggest/core/dictionary/word_property.cpp
@@ -33,15 +33,16 @@ void WordProperty::outputProperties(JNIEnv *const env, jintArray outCodePoints,
     jmethodID intToIntegerConstructorId = env->GetMethodID(integerClass, "<init>", "(I)V");
     jclass arrayListClass = env->FindClass("java/util/ArrayList");
     jmethodID addMethodId = env->GetMethodID(arrayListClass, "add", "(Ljava/lang/Object;)Z");
-    const int shortcutTargetCount = mShortcutTargets.size();
+    const int shortcutTargetCount = mShortcuts.size();
     for (int i = 0; i < shortcutTargetCount; ++i) {
-        jintArray shortcutTargetCodePointArray = env->NewIntArray(mShortcutTargets[i].size());
+        const std::vector<int> *const targetCodePoints = mShortcuts[i].getTargetCodePoints();
+        jintArray shortcutTargetCodePointArray = env->NewIntArray(targetCodePoints->size());
         env->SetIntArrayRegion(shortcutTargetCodePointArray, 0 /* start */,
-                mShortcutTargets[i].size(), &mShortcutTargets[i][0]);
+                targetCodePoints->size(), &targetCodePoints->at(0));
         env->CallVoidMethod(outShortcutTargets, addMethodId, shortcutTargetCodePointArray);
         env->DeleteLocalRef(shortcutTargetCodePointArray);
         jobject integerProbability = env->NewObject(integerClass, intToIntegerConstructorId,
-                mShortcutProbabilities[i]);
+                mShortcuts[i].getProbability());
         env->CallVoidMethod(outShortcutProbabilities, addMethodId, integerProbability);
         env->DeleteLocalRef(integerProbability);
     }
diff --git a/native/jni/src/suggest/core/dictionary/word_property.h b/native/jni/src/suggest/core/dictionary/word_property.h
index dcac8536aafff3efd7773e403bdbf47bf7350e14..69c880861514165a8112593611ca7768214f8d88 100644
--- a/native/jni/src/suggest/core/dictionary/word_property.h
+++ b/native/jni/src/suggest/core/dictionary/word_property.h
@@ -28,23 +28,54 @@ namespace latinime {
 // This class is used for returning information belonging to a word to java side.
 class WordProperty {
  public:
-    // TODO: Add bigram information.
+    class BigramProperty {
+     public:
+        BigramProperty(const std::vector<int> *const targetCodePoints,
+                const int probability, const int timestamp, const int level, const int count)
+                : mTargetCodePoints(*targetCodePoints), mProbability(probability),
+                  mTimestamp(timestamp), mLevel(level), mCount(count) {}
+
+     private:
+        std::vector<int> mTargetCodePoints;
+        int mProbability;
+        int mTimestamp;
+        int mLevel;
+        int mCount;
+    };
+
+    class ShortcutProperty {
+     public:
+        ShortcutProperty(const std::vector<int> *const targetCodePoints, const int probability)
+                : mTargetCodePoints(*targetCodePoints), mProbability(probability) {}
+
+        const std::vector<int> *getTargetCodePoints() const {
+            return &mTargetCodePoints;
+        }
+
+        int getProbability() const {
+            return mProbability;
+        }
+
+     private:
+        std::vector<int> mTargetCodePoints;
+        int mProbability;
+    };
+
     // Invalid word.
     WordProperty()
             : mCodePoints(), mIsNotAWord(false), mIsBlacklisted(false),
               mHasBigrams(false), mHasShortcuts(false), mProbability(NOT_A_PROBABILITY),
-              mTimestamp(0), mLevel(0), mCount(0), mShortcutTargets(), mShortcutProbabilities() {}
+              mTimestamp(0), mLevel(0), mCount(0), mBigrams(), mShortcuts() {}
 
     WordProperty(const std::vector<int> *const codePoints,
             const bool isNotAWord, const bool isBlacklisted, const bool hasBigrams,
             const bool hasShortcuts, const int probability, const int timestamp,
-            const int level, const int count,
-            const std::vector<std::vector<int> > *const shortcutTargets,
-            const std::vector<int> *const shortcutProbabilities)
+            const int level, const int count, const std::vector<BigramProperty> *const bigrams,
+            const std::vector<ShortcutProperty> *const shortcuts)
             : mCodePoints(*codePoints), mIsNotAWord(isNotAWord), mIsBlacklisted(isBlacklisted),
               mHasBigrams(hasBigrams), mHasShortcuts(hasShortcuts), mProbability(probability),
-              mTimestamp(timestamp), mLevel(level), mCount(count),
-              mShortcutTargets(*shortcutTargets), mShortcutProbabilities(*shortcutProbabilities) {}
+              mTimestamp(timestamp), mLevel(level), mCount(count), mBigrams(*bigrams),
+              mShortcuts(*shortcuts) {}
 
     void outputProperties(JNIEnv *const env, jintArray outCodePoints, jbooleanArray outFlags,
             jintArray outProbability, jintArray outHistoricalInfo, jobject outShortcutTargets,
@@ -63,9 +94,8 @@ class WordProperty {
     int mTimestamp;
     int mLevel;
     int mCount;
-    // Shortcut
-    std::vector<std::vector<int> > mShortcutTargets;
-    std::vector<int> mShortcutProbabilities;
+    std::vector<BigramProperty> mBigrams;
+    std::vector<ShortcutProperty> mShortcuts;
 };
 } // namespace latinime
 #endif // LATINIME_WORD_PROPERTY_H
diff --git a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp
index 0b067e127655fcc263f6db8a0643d086ed0bfae9..625b5349b5946c1561c63190bbc69c227b5bbfe0 100644
--- a/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp
+++ b/native/jni/src/suggest/policyimpl/dictionary/structure/v4/ver4_patricia_trie_policy.cpp
@@ -332,9 +332,10 @@ const WordProperty Ver4PatriciaTriePolicy::getWordProperty(const int *const code
             mBuffers.get()->getProbabilityDictContent()->getProbabilityEntry(
                     ptNodeParams.getTerminalId());
     const HistoricalInfo *const historicalInfo = probabilityEntry.getHistoricalInfo();
+    // TODO: Fetch bigram information.
+    std::vector<WordProperty::BigramProperty> bigrams;
     // Fetch shortcut information.
-    std::vector<std::vector<int> > shortcutTargets;
-    std::vector<int> shortcutProbabilities;
+    std::vector<WordProperty::ShortcutProperty> shortcuts;
     int shortcutPos = getShortcutPositionOfPtNode(ptNodePos);
     if (shortcutPos != NOT_A_DICT_POS) {
         int shortcutTarget[MAX_WORD_LENGTH];
@@ -347,15 +348,14 @@ const WordProperty Ver4PatriciaTriePolicy::getWordProperty(const int *const code
             shortcutDictContent->getShortcutEntryAndAdvancePosition(MAX_WORD_LENGTH, shortcutTarget,
                     &shortcutTargetLength, &shortcutProbability, &hasNext, &shortcutPos);
             std::vector<int> target(shortcutTarget, shortcutTarget + shortcutTargetLength);
-            shortcutTargets.push_back(target);
-            shortcutProbabilities.push_back(shortcutProbability);
+            shortcuts.push_back(WordProperty::ShortcutProperty(&target, shortcutProbability));
         }
     }
     return WordProperty(&codePointVector, ptNodeParams.isNotAWord(),
             ptNodeParams.isBlacklisted(), ptNodeParams.hasBigrams(),
             ptNodeParams.hasShortcutTargets(), ptNodeParams.getProbability(),
             historicalInfo->getTimeStamp(), historicalInfo->getLevel(),
-            historicalInfo->getCount(), &shortcutTargets, &shortcutProbabilities);
+            historicalInfo->getCount(), &bigrams, &shortcuts);
 }
 
 } // namespace latinime