I’m currently working on a Salesforce project that utilizes a few home-built managed packages. There are lots of restrictions of what you can and can’t do with managed package, and most of those are documented fairly clearly. Some, however, are somewhat hidden.

One such restriction is this:

Only custom objects, which are sObject types, of managed packages can be serialized from code that is external to the managed package. Objects that are instances of Apex classes defined in the managed package can’t be serialized. (JSON Support)

So if you are working in Sandbox Org (S), and have a class C inside of package P, you cannot call JSON.serialize(P.C).

It turns out though, there is a way around this that does not appear to be documented: virtual classes. Virtual classes are Salesforce’s version of abstract classes.

If you declare class C as “global virtual” inside of package P, and then extend it inside of your sandbox/production org/other package, you can serialize it.

//Inside package P
global virtual class C {
  global String testValue;
}

 

@isTest
private class TestFromSandbox {

    class Ext extends P.C { }

    @isTest static void testMethod() {
    try{ 
      JSON.serialize(new P.C());
      System.assert(false,'This should fail');
    } catch (Exception ex) {
      System.assertEquals('Cannot serialize type from package: P.C',ex.getMessage());
    }
    Ext virt = new Ext();
    virt.testValue = 'bla';
    System.assertEquals('{"testValue":"bla"}',JSON.serialize(virt));
  }
}