Skip to content

Instantly share code, notes, and snippets.

@westc
Last active October 28, 2023 02:41
Show Gist options
  • Save westc/d9e96f235afbbb9927cdb027ef25ed11 to your computer and use it in GitHub Desktop.
Save westc/d9e96f235afbbb9927cdb027ef25ed11 to your computer and use it in GitHub Desktop.
Apex class that interprets JSON values and allows for easy traversal and type casting.
public class JSONValue {
private Object objValue;
public JSONValue(String serialized) {
this.objValue = JSON.deserializeUntyped(serialized);
}
private JSONValue(Object unserialized) {
this.objValue = unserialized;
}
public JSONValue get(Object[] keys) {
JSONValue level = this;
for (Object key : keys) {
level = level.get(key);
}
return level;
}
public JSONValue get(Object key) {
return new JSONValue(this.getAsObject(key));
}
public Decimal getAsDecimal(Object key) {
Object objValue = getAsObject(key);
return objValue instanceof String
? Decimal.valueOf((String)objValue)
: Decimal.valueOf((Double)objValue);
}
public Boolean getAsBoolean(Object key) {
return (Boolean)getAsObject(key);
}
public Double getAsDouble(Object key) {
return (Double)getAsObject(key);
}
public Integer getAsInteger(Object key) {
return (Integer)getAsObject(key);
}
public String getAsString(Object key) {
return (String)getAsObject(key);
}
public Object getAsObject(Object keys) {
if (keys instanceof Object[]) {
Object level = this.objValue;
for (Object key : (Object[])keys) {
level = getAsObject(level, key);
}
return level;
}
return getAsObject(this.objValue, keys);
}
private static Object getAsObject(Object value, Object key) {
if (value instanceof Map<String,Object>) {
if (key instanceof String) {
Map<String,Object> mapValue = (Map<String,Object>)value;
String strKey = (String)key;
if (mapValue.containsKey(strKey)) {
return mapValue.get(strKey);
}
}
}
else if (value instanceof Object[]) {
if (key instanceof Integer) {
Object[] arrayValue = (Object[])value;
Integer intKey = (Integer)key;
Integer count = arrayValue.size();
if (intKey < 0) intKey += count;
if (0 <= intKey && intKey <= count) {
return arrayValue.get(intKey);
}
}
}
else {
throw new TypeException('You can only use getter on an array or a map.');
}
throw new TypeException('The specified key could not be found.');
}
public Integer asInteger() {
return (Integer)this.objValue;
}
public String asString() {
return (String)this.objValue;
}
public Boolean asBoolean() {
return (Boolean)this.objValue;
}
public Double asDouble() {
return (Double)this.objValue;
}
public Object asObject() {
return this.objValue;
}
public Decimal asDecimal() {
return this.objValue instanceof String
? Decimal.valueOf((String)this.objValue)
: Decimal.valueOf((Double)this.objValue);
}
}
String strJSON = '{"people":[{"firstName": "John","lastName":"Smith","attributes":{"isHuman":true,"isWeak":false}}]}';
JSONValue jv = new JSONValue(strJSON);
Assert.areEqual('John', jv.get('people').get(-1).get('firstName').asString());
Assert.areEqual('Smith', jv.get(new Object[]{'people', 0, 'lastName'}).asString());
Assert.areEqual(true, jv.get('people').get(0).get('attributes').getAsBoolean('isHuman'));
Assert.areEqual(false, jv.getAsBoolean(new Object[]{'people', -1, 'attributes', 'isWeak'}));
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment