ParseApplication/ExternalLibs/Parse-SDK-Android/Parse/src/main/java/com/parse/ParseObjectCurrentCoder.java

185 lines
5.9 KiB
Java

/*
* Copyright (c) 2015-present, Parse, LLC.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
package com.parse;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.Date;
import java.util.Iterator;
/**
* Handles encoding/decoding ParseObjects to/from /2 format JSON. /2 format json is only used for
* persisting current ParseObject(currentInstallation, currentUser) to disk when LDS is not enabled.
*/
/** package */ class ParseObjectCurrentCoder extends ParseObjectCoder {
/*
/2 format JSON Keys
*/
private static final String KEY_OBJECT_ID = "objectId";
private static final String KEY_CLASS_NAME = "classname";
private static final String KEY_CREATED_AT = "createdAt";
private static final String KEY_UPDATED_AT = "updatedAt";
private static final String KEY_DATA = "data";
/*
Old serialized JSON keys
*/
private static final String KEY_OLD_OBJECT_ID = "id";
private static final String KEY_OLD_CREATED_AT = "created_at";
private static final String KEY_OLD_UPDATED_AT = "updated_at";
private static final String KEY_OLD_POINTERS = "pointers";
private static final ParseObjectCurrentCoder INSTANCE =
new ParseObjectCurrentCoder();
public static ParseObjectCurrentCoder get() {
return INSTANCE;
}
/* package */ ParseObjectCurrentCoder() {
// do nothing
}
/**
* Converts a {@code ParseObject} to /2/ JSON representation suitable for saving to disk.
*
* <pre>
* {
* data: {
* // data fields, including objectId, createdAt, updatedAt
* },
* classname: class name for the object,
* operations: { } // operations per field
* }
* </pre>
*
* All keys are included, regardless of whether they are dirty.
*
* @see #decode(ParseObject.State.Init, JSONObject, ParseDecoder)
*/
@Override
public <T extends ParseObject.State> JSONObject encode(
T state, ParseOperationSet operations, ParseEncoder encoder) {
if (operations != null) {
throw new IllegalArgumentException("Parameter ParseOperationSet is not null");
}
// Public data goes in dataJSON; special fields go in objectJSON.
JSONObject objectJSON = new JSONObject();
JSONObject dataJSON = new JSONObject();
try {
// Serialize the data
for (String key : state.keySet()) {
Object object = state.get(key);
dataJSON.put(key, encoder.encode(object));
// TODO(grantland): Use cached value from hashedObjects, but only if we're not dirty.
}
if (state.createdAt() > 0) {
dataJSON.put(KEY_CREATED_AT,
ParseDateFormat.getInstance().format(new Date(state.createdAt())));
}
if (state.updatedAt() > 0) {
dataJSON.put(KEY_UPDATED_AT,
ParseDateFormat.getInstance().format(new Date(state.updatedAt())));
}
if (state.objectId() != null) {
dataJSON.put(KEY_OBJECT_ID, state.objectId());
}
objectJSON.put(KEY_DATA, dataJSON);
objectJSON.put(KEY_CLASS_NAME, state.className());
} catch (JSONException e) {
throw new RuntimeException("could not serialize object to JSON");
}
return objectJSON;
}
/**
* Decodes from /2/ JSON.
*
* This is only used to read ParseObjects stored on disk in JSON.
*
* @see #encode(ParseObject.State, ParseOperationSet, ParseEncoder)
*/
@Override
public <T extends ParseObject.State.Init<?>> T decode(
T builder, JSONObject json, ParseDecoder decoder) {
try {
// The handlers for id, created_at, updated_at, and pointers are for
// backward compatibility with old serialized users.
if (json.has(KEY_OLD_OBJECT_ID)) {
String newObjectId = json.getString(KEY_OLD_OBJECT_ID);
builder.objectId(newObjectId);
}
if (json.has(KEY_OLD_CREATED_AT)) {
String createdAtString =
json.getString(KEY_OLD_CREATED_AT);
if (createdAtString != null) {
builder.createdAt(ParseImpreciseDateFormat.getInstance().parse(createdAtString));
}
}
if (json.has(KEY_OLD_UPDATED_AT)) {
String updatedAtString =
json.getString(KEY_OLD_UPDATED_AT);
if (updatedAtString != null) {
builder.updatedAt(ParseImpreciseDateFormat.getInstance().parse(updatedAtString));
}
}
if (json.has(KEY_OLD_POINTERS)) {
JSONObject newPointers =
json.getJSONObject(KEY_OLD_POINTERS);
Iterator<?> keys = newPointers.keys();
while (keys.hasNext()) {
String key = (String) keys.next();
JSONArray pointerArray = newPointers.getJSONArray(key);
builder.put(key, ParseObject.createWithoutData(pointerArray.optString(0),
pointerArray.optString(1)));
}
}
JSONObject data = json.optJSONObject(KEY_DATA);
if (data != null) {
Iterator<?> keys = data.keys();
while (keys.hasNext()) {
String key = (String) keys.next();
if (key.equals(KEY_OBJECT_ID)) {
String newObjectId = data.getString(key);
builder.objectId(newObjectId);
continue;
}
if (key.equals(KEY_CREATED_AT)) {
builder.createdAt(ParseDateFormat.getInstance().parse(data.getString(key)));
continue;
}
if (key.equals(KEY_UPDATED_AT)) {
builder.updatedAt(ParseDateFormat.getInstance().parse(data.getString(key)));
continue;
}
Object value = data.get(key);
Object decodedObject = decoder.decode(value);
builder.put(key, decodedObject);
}
}
return builder;
} catch (JSONException e) {
throw new RuntimeException(e);
}
}
}