Well, this is how you can do it. Apex is made through Java!
String jsonText = '{"Data": {"attributes": {"type": "Contact","url":"/services/data/v35.0/sobjects/Contact/0036100000JUXKkAAP"},"Id": "0036100000JUXKkAAP","Description": "","LastName": "Testing"}}';
Map<String, Object> cObjMap = (Map<String, Object>) JSON.deserializeUntyped(jsonText);
String cObjJson = JSON.serialize(cObjMap.get('Data'));
// Why again :(
Map<String, Object> cObjMapFurious = (Map<String, Object>) JSON.deserializeUntyped(cObjJson);
String cObjJsonDrunk = JSON.serialize(cObjMapFurious);
try
{
SObject customObject = (SObject)JSON.deserialize(cObjJsonDrunk, Sobject.class);
System.debug(' Accomplished: '+customObject);
}
catch(Exception ex)
{
System.debug(' @@@@@ Don\'t visible '+ex.getMessage());
}
I think you should revisit the idea of using an abstract
class rather than an interface. You can use the former to enforce a contract.
public class Demo
{
final String typeName;
public String getSomeProperty() { return typeName; }
public abstract List<User> doStuff();
}
Granted, this definition cannot be constructed either, but deserialization into this type is allowed.
Demo instance = (Demo)JSON.deserialize('{}', Demo.class);
system.debug(instance.getSomeProperty());
And the contract gets enforced, for if you try to save a class which doesn't implement the method:
class Foo extends Demo { }
You get a compile-time error:
Class Foo must implement the abstract method: List<User> Demo.doStuff()
As a benefit, properties like typeName
can be preserved throughout the serialization round-trip.
Here's a simple demonstration of that process. First define this extension:
public class Foo extends Demo
{
final String profileName;
public override List<User> doStuff()
{
return [
SELECT Username FROM User
WHERE Profile.Name = :profileName
];
}
}
Now run this script:
String payload = '{"typeName": "Foo", "profileName": "System Administrator"}';
Map<String, Object> controllerData = (Map<String, Object>)JSON.deserializeUntyped(payload);
String controllerType = (String)controllerData.get('typeName');
Demo controller;
if (controllerType != null)
{
controller = (Demo)JSON.deserialize(payload, Type.forName(controllerType));
system.debug(controller.doStuff());
}
As far as why your repo works in aura but not in a pure Apex context, it looks like the system acts similarly to Visualforce, treating methods prefixed with get
as properties and adding them to the serialization (since the end result is indecipherable from { get; set; }
notation). If you had named your method retrieveName
instead of getName
, I suspect it would not have worked in aura either. You can hack around it with mimicry along the lines of:
public class MyClass
{
final String name = getName();
public String getName() { return 'MyClass'; }
}
But I suspect that's not a tenable long-term solution.
Best Answer
Assuming the system that is creating the JSON is using base64 encoding for the image, yes use Blob.
Here is an example of the deserialization/serialization working with base64 in Apex: