[SalesForce] JSONGenerator writeObject() generates private properties

I have an Apex Class with some public properties and some private properties. When I use JSONGenerator.writeObject(foo), private properties are written into the JSON string. My code is below.

public class foo { 
   public String id;
   public String name;
   private String endpoint;
}

I have the following code that generates the JSON:

foo item = new foo();
item.Name = 'Truck';
system.JSONGenerator gen = JSON.createGenerator(true);
gen.writeStartObject();
gen.writeFieldName('requests');
gen.writeStartArray();
gen.writeStartObject();
gen.writeObjectField('method', method);
gen.writeFieldName('body');
gen.writeObject(item);
system.debug('gen.getAsString():' + gen.getAsString());

The JSON output looks like this:

    {"requests" : [ 
       {"body" : {
          "name" : "Truck",
          "id" : null,
          "endpoint" : null
          }
       } ]
     }

For some reason the private properties are being rendered. Is this normal behavior?

Best Answer

Yes :) this expected. De/serialization is a symmetrical process that doesn't "lose" data.

  1. If that process were asymmetrical, objects would be inadvertently corrupted by serialization.

  2. To prevent intentional object mutation, Salesforce prohibit serialization across namespaces.

    Object o = new Channel_Orders.ServiceOrderProcessor();
    Json.serialize(o);
    
    //System.JSONException:
    //Cannot serialize type from package: CHANNEL_ORDERS.ServiceOrderProcessor
    

I think the intention being (eg) one should be able to take the "dehydrated" string and write it away into storage, then hydrate it back into the original. The object himself should be none the wiser.

Similarly the constructor is not called when deserializing an object - that part of the lifecycle was "someone else's responsibility" independent of his existence for a while as JSON.

Note: using the transient keyword will exclude those properties when serialized.

Related Topic