2

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?

4

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.

  • was a surprise to me this, but transient saved me, never used it in this context. Anyway i don't find proper this behaviour, because i expect that what i declare as private (without get/set) is "private", in meaning that are internal mechanics and don't risk to impact/confuse the rest of the world... – Klodj_Meta Nov 15 '17 at 17:38
0

Use writeNullField method.

if(FIELD!=null)
    gen.writeObjectField(FIELD, VALUE);
else 
    gen.writeNullField(FIELD);

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.