]> nmode's Git Repositories - signal-cli/commitdiff
Make Json store use Jackson instead of Gson (as it's already linked)
authorxardas <xardas@rutarget.ru>
Tue, 6 Oct 2015 18:34:26 +0000 (21:34 +0300)
committerAsamK <asamk@gmx.de>
Tue, 6 Oct 2015 19:39:12 +0000 (21:39 +0200)
Closes #4

src/main/java/cli/JsonAxolotlStore.java
src/main/java/cli/JsonIdentityKeyStore.java
src/main/java/cli/JsonPreKeyStore.java
src/main/java/cli/JsonSessionStore.java
src/main/java/cli/JsonSignedPreKeyStore.java
src/main/java/cli/Manager.java

index 02b9cdf1bc3ce152922556257c90781f81bc17fc..57282f129d1bc5a87f11cc1957b28f534dd49769 100644 (file)
@@ -1,5 +1,8 @@
 package cli;
 
+import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
+import com.fasterxml.jackson.databind.annotation.JsonSerialize;
 import org.json.JSONObject;
 import org.whispersystems.libaxolotl.*;
 import org.whispersystems.libaxolotl.state.AxolotlStore;
@@ -11,17 +14,35 @@ import java.io.IOException;
 import java.util.List;
 
 class JsonAxolotlStore implements AxolotlStore {
-    private final JsonPreKeyStore preKeyStore;
-    private final JsonSessionStore sessionStore;
-    private final JsonSignedPreKeyStore signedPreKeyStore;
 
-    private final JsonIdentityKeyStore identityKeyStore;
+    @JsonProperty("preKeys")
+    @JsonDeserialize(using = JsonPreKeyStore.JsonPreKeyStoreDeserializer.class)
+    @JsonSerialize(using = JsonPreKeyStore.JsonPreKeyStoreSerializer.class)
+    protected JsonPreKeyStore preKeyStore;
 
-    public JsonAxolotlStore(JSONObject jsonAxolotl) throws IOException, InvalidKeyException {
-        this.preKeyStore = new JsonPreKeyStore(jsonAxolotl.getJSONArray("preKeys"));
-        this.sessionStore = new JsonSessionStore(jsonAxolotl.getJSONArray("sessionStore"));
-        this.signedPreKeyStore = new JsonSignedPreKeyStore(jsonAxolotl.getJSONArray("signedPreKeyStore"));
-        this.identityKeyStore = new JsonIdentityKeyStore(jsonAxolotl.getJSONObject("identityKeyStore"));
+    @JsonProperty("sessionStore")
+    @JsonDeserialize(using = JsonSessionStore.JsonSessionStoreDeserializer.class)
+    @JsonSerialize(using = JsonSessionStore.JsonPreKeyStoreSerializer.class)
+    protected JsonSessionStore sessionStore;
+
+    @JsonProperty("signedPreKeyStore")
+    @JsonDeserialize(using = JsonSignedPreKeyStore.JsonSignedPreKeyStoreDeserializer.class)
+    @JsonSerialize(using = JsonSignedPreKeyStore.JsonSignedPreKeyStoreSerializer.class)
+    protected JsonSignedPreKeyStore signedPreKeyStore;
+
+    @JsonProperty("identityKeyStore")
+    @JsonDeserialize(using = JsonIdentityKeyStore.JsonIdentityKeyStoreDeserializer.class)
+    @JsonSerialize(using = JsonIdentityKeyStore.JsonIdentityKeyStoreSerializer.class)
+    protected JsonIdentityKeyStore identityKeyStore;
+
+    public JsonAxolotlStore() {
+    }
+
+    public JsonAxolotlStore(JsonPreKeyStore preKeyStore, JsonSessionStore sessionStore, JsonSignedPreKeyStore signedPreKeyStore, JsonIdentityKeyStore identityKeyStore) {
+        this.preKeyStore = preKeyStore;
+        this.sessionStore = sessionStore;
+        this.signedPreKeyStore = signedPreKeyStore;
+        this.identityKeyStore = identityKeyStore;
     }
 
     public JsonAxolotlStore(IdentityKeyPair identityKeyPair, int registrationId) {
@@ -31,13 +52,6 @@ class JsonAxolotlStore implements AxolotlStore {
         this.identityKeyStore = new JsonIdentityKeyStore(identityKeyPair, registrationId);
     }
 
-    public JSONObject getJson() {
-        return new JSONObject().put("preKeys", preKeyStore.getJson())
-                .put("sessionStore", sessionStore.getJson())
-                .put("signedPreKeyStore", signedPreKeyStore.getJson())
-                .put("identityKeyStore", identityKeyStore.getJson());
-    }
-
     @Override
     public IdentityKeyPair getIdentityKeyPair() {
         return identityKeyStore.getIdentityKeyPair();
index 827bf055d0e8c52963d395e4a2d269995e395382..8577526d64e8dfd46e9596cab1f0394430ca6ae2 100644 (file)
@@ -1,7 +1,9 @@
 package cli;
 
-import org.json.JSONArray;
-import org.json.JSONObject;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.*;
 import org.whispersystems.libaxolotl.IdentityKey;
 import org.whispersystems.libaxolotl.IdentityKeyPair;
 import org.whispersystems.libaxolotl.InvalidKeyException;
@@ -18,37 +20,14 @@ class JsonIdentityKeyStore implements IdentityKeyStore {
     private final IdentityKeyPair identityKeyPair;
     private final int localRegistrationId;
 
-    public JsonIdentityKeyStore(JSONObject jsonAxolotl) throws IOException, InvalidKeyException {
-        localRegistrationId = jsonAxolotl.getInt("registrationId");
-        identityKeyPair = new IdentityKeyPair(Base64.decode(jsonAxolotl.getString("identityKey")));
-
-        JSONArray list = jsonAxolotl.getJSONArray("trustedKeys");
-        for (int i = 0; i < list.length(); i++) {
-            JSONObject k = list.getJSONObject(i);
-            try {
-                trustedKeys.put(k.getString("name"), new IdentityKey(Base64.decode(k.getString("identityKey")), 0));
-            } catch (InvalidKeyException | IOException e) {
-                System.out.println("Error while decoding key for: " + k.getString("name"));
-            }
-        }
-    }
 
     public JsonIdentityKeyStore(IdentityKeyPair identityKeyPair, int localRegistrationId) {
         this.identityKeyPair = identityKeyPair;
         this.localRegistrationId = localRegistrationId;
     }
 
-    public JSONObject getJson() {
-        JSONArray list = new JSONArray();
-        for (String name : trustedKeys.keySet()) {
-            list.put(new JSONObject().put("name", name).put("identityKey", Base64.encodeBytes(trustedKeys.get(name).serialize())));
-        }
-
-        JSONObject result = new JSONObject();
-        result.put("registrationId", localRegistrationId);
-        result.put("identityKey", Base64.encodeBytes(identityKeyPair.serialize()));
-        result.put("trustedKeys", list);
-        return result;
+    public void addTrustedKeys(Map<String, IdentityKey> keyMap) {
+        trustedKeys.putAll(keyMap);
     }
 
     @Override
@@ -71,4 +50,58 @@ class JsonIdentityKeyStore implements IdentityKeyStore {
         IdentityKey trusted = trustedKeys.get(name);
         return (trusted == null || trusted.equals(identityKey));
     }
+
+    public static class JsonIdentityKeyStoreDeserializer extends JsonDeserializer<JsonIdentityKeyStore> {
+
+        @Override
+        public JsonIdentityKeyStore deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
+            JsonNode node = jsonParser.getCodec().readTree(jsonParser);
+
+            try {
+                int localRegistrationId = node.get("registrationId").asInt();
+                IdentityKeyPair identityKeyPair = new IdentityKeyPair(Base64.decode(node.get("identityKey").asText()));
+
+
+                Map<String, IdentityKey> trustedKeyMap = new HashMap<>();
+                JsonNode trustedKeysNode = node.get("trustedKeys");
+                if (trustedKeysNode.isArray()) {
+                    for (JsonNode trustedKey : trustedKeysNode) {
+                        String trustedKeyName = trustedKey.get("name").asText();
+                        try {
+                            trustedKeyMap.put(trustedKeyName, new IdentityKey(Base64.decode(trustedKey.get("identityKey").asText()), 0));
+                        }  catch (InvalidKeyException | IOException e) {
+                            System.out.println(String.format("Error while decoding key for: %s", trustedKeyName));
+                        }
+                    }
+                }
+
+                JsonIdentityKeyStore keyStore = new JsonIdentityKeyStore(identityKeyPair, localRegistrationId);
+                keyStore.addTrustedKeys(trustedKeyMap);
+
+                return keyStore;
+
+            } catch (InvalidKeyException e) {
+                throw new IOException(e);
+            }
+        }
+    }
+
+    public static class JsonIdentityKeyStoreSerializer extends JsonSerializer<JsonIdentityKeyStore> {
+
+        @Override
+        public void serialize(JsonIdentityKeyStore jsonIdentityKeyStore, JsonGenerator json, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
+            json.writeStartObject();
+            json.writeNumberField("registrationId", jsonIdentityKeyStore.getLocalRegistrationId());
+            json.writeStringField("identityKey", Base64.encodeBytes(jsonIdentityKeyStore.getIdentityKeyPair().serialize()));
+            json.writeArrayFieldStart("trustedKeys");
+            for (Map.Entry<String, IdentityKey> trustedKey : jsonIdentityKeyStore.trustedKeys.entrySet()) {
+                json.writeStartObject();
+                json.writeStringField("name", trustedKey.getKey());
+                json.writeStringField("identityKey", Base64.encodeBytes(trustedKey.getValue().serialize()));
+                json.writeEndObject();
+            }
+            json.writeEndArray();
+            json.writeEndObject();
+        }
+    }
 }
index a0133ec8e41ca77fdadbe5fe9c52feb972df00d7..1ae297ecc59e0e61f7679b5635b7747f5cc8ce8e 100644 (file)
@@ -1,7 +1,9 @@
 package cli;
 
-import org.json.JSONArray;
-import org.json.JSONObject;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.*;
 import org.whispersystems.libaxolotl.InvalidKeyIdException;
 import org.whispersystems.libaxolotl.state.PreKeyRecord;
 import org.whispersystems.libaxolotl.state.PreKeyStore;
@@ -14,27 +16,13 @@ class JsonPreKeyStore implements PreKeyStore {
 
     private final Map<Integer, byte[]> store = new HashMap<>();
 
-    public JsonPreKeyStore() {
 
-    }
+    public JsonPreKeyStore() {
 
-    public JsonPreKeyStore(JSONArray list) {
-        for (int i = 0; i < list.length(); i++) {
-            JSONObject k = list.getJSONObject(i);
-            try {
-                store.put(k.getInt("id"), Base64.decode(k.getString("record")));
-            } catch (IOException e) {
-                System.out.println("Error while decoding prekey for: " + k.getString("name"));
-            }
-        }
     }
 
-    public JSONArray getJson() {
-        JSONArray result = new JSONArray();
-        for (Integer id : store.keySet()) {
-            result.put(new JSONObject().put("id", id.toString()).put("record", Base64.encodeBytes(store.get(id))));
-        }
-        return result;
+    public void addPreKeys(Map<Integer, byte[]> preKeys) {
+        store.putAll(preKeys);
     }
 
     @Override
@@ -64,4 +52,46 @@ class JsonPreKeyStore implements PreKeyStore {
     public void removePreKey(int preKeyId) {
         store.remove(preKeyId);
     }
+
+    public static class JsonPreKeyStoreDeserializer extends JsonDeserializer<JsonPreKeyStore> {
+
+        @Override
+        public JsonPreKeyStore deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
+            JsonNode node = jsonParser.getCodec().readTree(jsonParser);
+
+
+            Map<Integer, byte[]> preKeyMap = new HashMap<>();
+            if (node.isArray()) {
+                for (JsonNode preKey : node) {
+                    Integer preKeyId = preKey.get("id").asInt();
+                    try {
+                        preKeyMap.put(preKeyId, Base64.decode(preKey.get("record").asText()));
+                    }  catch (IOException e) {
+                        System.out.println(String.format("Error while decoding prekey for: %s", preKeyId));
+                    }
+                }
+            }
+
+            JsonPreKeyStore keyStore = new JsonPreKeyStore();
+            keyStore.addPreKeys(preKeyMap);
+
+            return keyStore;
+
+        }
+    }
+
+    public static class JsonPreKeyStoreSerializer extends JsonSerializer<JsonPreKeyStore> {
+
+        @Override
+        public void serialize(JsonPreKeyStore jsonPreKeyStore, JsonGenerator json, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
+            json.writeStartArray();
+            for (Map.Entry<Integer, byte[]> preKey : jsonPreKeyStore.store.entrySet()) {
+                json.writeStartObject();
+                json.writeNumberField("id", preKey.getKey());
+                json.writeStringField("record", Base64.encodeBytes(preKey.getValue()));
+                json.writeEndObject();
+            }
+            json.writeEndArray();
+        }
+    }
 }
index d2fe0a4a7c428b387f44fa48ff3d4330d28fb49b..c70fa5cf692418b11f2d6c3f981e36e771adbc2f 100644 (file)
@@ -1,7 +1,9 @@
 package cli;
 
-import org.json.JSONArray;
-import org.json.JSONObject;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.*;
 import org.whispersystems.libaxolotl.AxolotlAddress;
 import org.whispersystems.libaxolotl.state.SessionRecord;
 import org.whispersystems.libaxolotl.state.SessionStore;
@@ -17,26 +19,10 @@ class JsonSessionStore implements SessionStore {
 
     }
 
-    public JsonSessionStore(JSONArray list) {
-        for (int i = 0; i < list.length(); i++) {
-            JSONObject k = list.getJSONObject(i);
-            try {
-                sessions.put(new AxolotlAddress(k.getString("name"), k.getInt("deviceId")), Base64.decode(k.getString("record")));
-            } catch (IOException e) {
-                System.out.println("Error while decoding prekey for: " + k.getString("name"));
-            }
-        }
+    public void addSessions(Map<AxolotlAddress, byte[]> sessions) {
+        this.sessions.putAll(sessions);
     }
 
-    public JSONArray getJson() {
-        JSONArray result = new JSONArray();
-        for (AxolotlAddress address : sessions.keySet()) {
-            result.put(new JSONObject().put("name", address.getName()).
-                    put("deviceId", address.getDeviceId()).
-                    put("record", Base64.encodeBytes(sessions.get(address))));
-        }
-        return result;
-    }
 
     @Override
     public synchronized SessionRecord loadSession(AxolotlAddress remoteAddress) {
@@ -88,4 +74,46 @@ class JsonSessionStore implements SessionStore {
             }
         }
     }
+
+    public static class JsonSessionStoreDeserializer extends JsonDeserializer<JsonSessionStore> {
+
+        @Override
+        public JsonSessionStore deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
+            JsonNode node = jsonParser.getCodec().readTree(jsonParser);
+
+            Map<AxolotlAddress, byte[]> sessionMap = new HashMap<>();
+            if (node.isArray()) {
+                for (JsonNode session : node) {
+                    String sessionName = session.get("name").asText();
+                    try {
+                        sessionMap.put(new AxolotlAddress(sessionName, session.get("deviceId").asInt()), Base64.decode(session.get("record").asText()));
+                    }  catch (IOException e) {
+                        System.out.println(String.format("Error while decoding session for: %s", sessionName));
+                    }
+                }
+            }
+
+            JsonSessionStore sessionStore = new JsonSessionStore();
+            sessionStore.addSessions(sessionMap);
+
+            return sessionStore;
+
+        }
+    }
+
+    public static class JsonPreKeyStoreSerializer extends JsonSerializer<JsonSessionStore> {
+
+        @Override
+        public void serialize(JsonSessionStore jsonSessionStore, JsonGenerator json, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
+            json.writeStartArray();
+            for (Map.Entry<AxolotlAddress, byte[]> preKey : jsonSessionStore.sessions.entrySet()) {
+                json.writeStartObject();
+                json.writeStringField("name", preKey.getKey().getName());
+                json.writeNumberField("deviceId", preKey.getKey().getDeviceId());
+                json.writeStringField("record", Base64.encodeBytes(preKey.getValue()));
+                json.writeEndObject();
+            }
+            json.writeEndArray();
+        }
+    }
 }
index f992d2d6101318fb622577e719866fa06a451d4b..9b48fa97034763b865e01ad4450081c6bcf33212 100644 (file)
@@ -1,7 +1,9 @@
 package cli;
 
-import org.json.JSONArray;
-import org.json.JSONObject;
+import com.fasterxml.jackson.core.JsonGenerator;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.*;
 import org.whispersystems.libaxolotl.InvalidKeyIdException;
 import org.whispersystems.libaxolotl.state.SignedPreKeyRecord;
 import org.whispersystems.libaxolotl.state.SignedPreKeyStore;
@@ -20,23 +22,9 @@ class JsonSignedPreKeyStore implements SignedPreKeyStore {
 
     }
 
-    public JsonSignedPreKeyStore(JSONArray list) {
-        for (int i = 0; i < list.length(); i++) {
-            JSONObject k = list.getJSONObject(i);
-            try {
-                store.put(k.getInt("id"), Base64.decode(k.getString("record")));
-            } catch (IOException e) {
-                System.out.println("Error while decoding prekey for: " + k.getString("name"));
-            }
-        }
-    }
 
-    public JSONArray getJson() {
-        JSONArray result = new JSONArray();
-        for (Integer id : store.keySet()) {
-            result.put(new JSONObject().put("id", id.toString()).put("record", Base64.encodeBytes(store.get(id))));
-        }
-        return result;
+    public void addSignedPreKeys(Map<Integer, byte[]> preKeys) {
+        store.putAll(preKeys);
     }
 
     @Override
@@ -81,4 +69,46 @@ class JsonSignedPreKeyStore implements SignedPreKeyStore {
     public void removeSignedPreKey(int signedPreKeyId) {
         store.remove(signedPreKeyId);
     }
+
+    public static class JsonSignedPreKeyStoreDeserializer extends JsonDeserializer<JsonSignedPreKeyStore> {
+
+        @Override
+        public JsonSignedPreKeyStore deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
+            JsonNode node = jsonParser.getCodec().readTree(jsonParser);
+
+
+            Map<Integer, byte[]> preKeyMap = new HashMap<>();
+            if (node.isArray()) {
+                for (JsonNode preKey : node) {
+                    Integer preKeyId = preKey.get("id").asInt();
+                    try {
+                        preKeyMap.put(preKeyId, Base64.decode(preKey.get("record").asText()));
+                    }  catch (IOException e) {
+                        System.out.println(String.format("Error while decoding prekey for: %s", preKeyId));
+                    }
+                }
+            }
+
+            JsonSignedPreKeyStore keyStore = new JsonSignedPreKeyStore();
+            keyStore.addSignedPreKeys(preKeyMap);
+
+            return keyStore;
+
+        }
+    }
+
+    public static class JsonSignedPreKeyStoreSerializer extends JsonSerializer<JsonSignedPreKeyStore> {
+
+        @Override
+        public void serialize(JsonSignedPreKeyStore jsonPreKeyStore, JsonGenerator json, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {
+            json.writeStartArray();
+            for (Map.Entry<Integer, byte[]> signedPreKey : jsonPreKeyStore.store.entrySet()) {
+                json.writeStartObject();
+                json.writeNumberField("id", signedPreKey.getKey());
+                json.writeStringField("record", Base64.encodeBytes(signedPreKey.getValue()));
+                json.writeEndObject();
+            }
+            json.writeEndArray();
+        }
+    }
 }
index 846e0dc9de63ba36cd6a373350081d6f12859289..4d8c733fd3cb82df51115f4e033ee38cce81cd24 100644 (file)
  */
 package cli;
 
-import org.apache.commons.io.IOUtils;
-import org.json.JSONObject;
+import com.fasterxml.jackson.annotation.JsonAutoDetect;
+import com.fasterxml.jackson.annotation.PropertyAccessor;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
+import com.fasterxml.jackson.databind.node.ObjectNode;
 import org.whispersystems.libaxolotl.*;
 import org.whispersystems.libaxolotl.ecc.Curve;
 import org.whispersystems.libaxolotl.ecc.ECKeyPair;
@@ -59,6 +64,7 @@ class Manager {
     private final static String dataPath = settingsPath + "/data";
     private final static String attachmentsPath = settingsPath + "/attachments";
 
+    private final ObjectMapper jsonProcessot = new ObjectMapper();
     private String username;
     private String password;
     private String signalingKey;
@@ -72,6 +78,10 @@ class Manager {
 
     public Manager(String username) {
         this.username = username;
+        jsonProcessot.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.NONE); // disable autodetect
+        jsonProcessot.enable(SerializationFeature.INDENT_OUTPUT); // for pretty print, you can disable it.
+        jsonProcessot.enable(SerializationFeature.WRITE_NULL_MAP_VALUES);
+        jsonProcessot.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
     }
 
     public String getFileName() {
@@ -88,43 +98,53 @@ class Manager {
         return axolotlStore != null;
     }
 
+    private JsonNode getNotNullNode(JsonNode parent, String name) throws InvalidObjectException {
+        JsonNode node = parent.get(name);
+        if (node == null) {
+            throw new InvalidObjectException(String.format("Incorrect file format: expected parameter %s not found ", name));
+        }
+
+        return node;
+    }
+
+
     public void load() throws IOException, InvalidKeyException {
-        JSONObject in = new JSONObject(IOUtils.toString(new FileInputStream(getFileName())));
-        username = in.getString("username");
-        password = in.getString("password");
-        if (in.has("signalingKey")) {
-            signalingKey = in.getString("signalingKey");
+        JsonNode rootNode = jsonProcessot.readTree(new File(getFileName()));
+
+        username = getNotNullNode(rootNode, "username").asText();
+        password = getNotNullNode(rootNode, "password").asText();
+        if (rootNode.has("signalingKey")) {
+            signalingKey = getNotNullNode(rootNode, "signalingKey").asText();
         }
-        if (in.has("preKeyIdOffset")) {
-            preKeyIdOffset = in.getInt("preKeyIdOffset");
+        if (rootNode.has("preKeyIdOffset")) {
+            preKeyIdOffset = getNotNullNode(rootNode, "preKeyIdOffset").asInt(0);
         } else {
             preKeyIdOffset = 0;
         }
-        if (in.has("nextSignedPreKeyId")) {
-            nextSignedPreKeyId = in.getInt("nextSignedPreKeyId");
+        if (rootNode.has("nextSignedPreKeyId")) {
+            nextSignedPreKeyId = getNotNullNode(rootNode, "nextSignedPreKeyId").asInt();
         } else {
             nextSignedPreKeyId = 0;
         }
-        axolotlStore = new JsonAxolotlStore(in.getJSONObject("axolotlStore"));
-        registered = in.getBoolean("registered");
+        axolotlStore = jsonProcessot.convertValue(getNotNullNode(rootNode, "axolotlStore"), JsonAxolotlStore.class); //new JsonAxolotlStore(in.getJSONObject("axolotlStore"));
+        registered = getNotNullNode(rootNode, "registered").asBoolean();
         accountManager = new TextSecureAccountManager(URL, TRUST_STORE, username, password, USER_AGENT);
     }
 
     public void save() {
-        String out = new JSONObject().put("username", username)
+        ObjectNode rootNode = jsonProcessot.createObjectNode();
+        rootNode.put("username", username)
                 .put("password", password)
                 .put("signalingKey", signalingKey)
                 .put("preKeyIdOffset", preKeyIdOffset)
                 .put("nextSignedPreKeyId", nextSignedPreKeyId)
-                .put("axolotlStore", axolotlStore.getJson())
-                .put("registered", registered).toString();
+                .put("registered", registered)
+                .putPOJO("axolotlStore", axolotlStore)
+        ;
         try {
-            OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(getFileName()));
-            writer.write(out);
-            writer.flush();
-            writer.close();
+            jsonProcessot.writeValue(new File(getFileName()), rootNode);
         } catch (Exception e) {
-            System.err.println("Saving file error: " + e.getMessage());
+            System.err.println(String.format("Error saving file: %s", e.getMessage()));
         }
     }