136 lines
4.7 KiB
Java
136 lines
4.7 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.JSONException;
|
|
import org.json.JSONObject;
|
|
|
|
import java.util.Iterator;
|
|
|
|
/**
|
|
* Handles encoding/decoding ParseObjects to/from REST JSON.
|
|
*/
|
|
/** package */ class ParseObjectCoder {
|
|
|
|
private static final String KEY_OBJECT_ID = "objectId";
|
|
private static final String KEY_CLASS_NAME = "className";
|
|
private static final String KEY_ACL = "ACL";
|
|
private static final String KEY_CREATED_AT = "createdAt";
|
|
private static final String KEY_UPDATED_AT = "updatedAt";
|
|
|
|
private static final ParseObjectCoder INSTANCE = new ParseObjectCoder();
|
|
public static ParseObjectCoder get() {
|
|
return INSTANCE;
|
|
}
|
|
|
|
/* package */ ParseObjectCoder() {
|
|
// do nothing
|
|
}
|
|
|
|
/**
|
|
* Converts a {@code ParseObject.State} to REST JSON for saving.
|
|
*
|
|
* Only dirty keys from {@code operations} are represented in the data. Non-dirty keys such as
|
|
* {@code updatedAt}, {@code createdAt}, etc. are not included.
|
|
*
|
|
* @param state
|
|
* {@link ParseObject.State} of the type of {@link ParseObject} that will be returned.
|
|
* Properties are completely ignored.
|
|
* @param operations
|
|
* Dirty operations that are to be saved.
|
|
* @param encoder
|
|
* Encoder instance that will be used to encode the request.
|
|
* @return
|
|
* A REST formatted {@link JSONObject} that will be used for saving.
|
|
*/
|
|
public <T extends ParseObject.State> JSONObject encode(
|
|
T state, ParseOperationSet operations, ParseEncoder encoder) {
|
|
JSONObject objectJSON = new JSONObject();
|
|
|
|
try {
|
|
// Serialize the data
|
|
for (String key : operations.keySet()) {
|
|
ParseFieldOperation operation = operations.get(key);
|
|
objectJSON.put(key, encoder.encode(operation));
|
|
|
|
// TODO(grantland): Use cached value from hashedObjects if it's a set operation.
|
|
}
|
|
|
|
if (state.objectId() != null) {
|
|
objectJSON.put(KEY_OBJECT_ID, state.objectId());
|
|
}
|
|
} catch (JSONException e) {
|
|
throw new RuntimeException("could not serialize object to JSON");
|
|
}
|
|
|
|
return objectJSON;
|
|
}
|
|
|
|
/**
|
|
* Converts REST JSON response to {@link ParseObject.State.Init}.
|
|
*
|
|
* This returns Builder instead of a State since we'll probably want to set some additional
|
|
* properties on it after decoding such as {@link ParseObject.State.Init#isComplete()}, etc.
|
|
*
|
|
* @param builder
|
|
* A {@link ParseObject.State.Init} instance that will have the server JSON applied
|
|
* (mutated) to it. This will generally be a instance created by clearing a mutable
|
|
* copy of a {@link ParseObject.State} to ensure it's an instance of the correct
|
|
* subclass: {@code state.newBuilder().clear()}
|
|
* @param json
|
|
* JSON response in REST format from the server.
|
|
* @param decoder
|
|
* Decoder instance that will be used to decode the server response.
|
|
* @return
|
|
* The same Builder instance passed in after the JSON is applied.
|
|
*/
|
|
public <T extends ParseObject.State.Init<?>> T decode(
|
|
T builder, JSONObject json, ParseDecoder decoder) {
|
|
try {
|
|
Iterator<?> keys = json.keys();
|
|
while (keys.hasNext()) {
|
|
String key = (String) keys.next();
|
|
/*
|
|
__type: Returned by queries and cloud functions to designate body is a ParseObject
|
|
__className: Used by fromJSON, should be stripped out by the time it gets here...
|
|
*/
|
|
if (key.equals("__type") || key.equals(KEY_CLASS_NAME)) {
|
|
continue;
|
|
}
|
|
if (key.equals(KEY_OBJECT_ID)) {
|
|
String newObjectId = json.getString(key);
|
|
builder.objectId(newObjectId);
|
|
continue;
|
|
}
|
|
if (key.equals(KEY_CREATED_AT)) {
|
|
builder.createdAt(ParseDateFormat.getInstance().parse(json.getString(key)));
|
|
continue;
|
|
}
|
|
if (key.equals(KEY_UPDATED_AT)) {
|
|
builder.updatedAt(ParseDateFormat.getInstance().parse(json.getString(key)));
|
|
continue;
|
|
}
|
|
if (key.equals(KEY_ACL)) {
|
|
ParseACL acl = ParseACL.createACLFromJSONObject(json.getJSONObject(key), decoder);
|
|
builder.put(KEY_ACL, acl);
|
|
continue;
|
|
}
|
|
|
|
Object value = json.get(key);
|
|
Object decodedObject = decoder.decode(value);
|
|
builder.put(key, decodedObject);
|
|
}
|
|
|
|
return builder;
|
|
} catch (JSONException e) {
|
|
throw new RuntimeException(e);
|
|
}
|
|
}
|
|
}
|