@Override
    public void serialize(CloudBlobMetadata value, JsonGenerator gen, SerializerProvider provider) throws IOException {

      gen.writeStartObject();
      // Required fields
      gen.writeStringField(FIELD_ID, value.id);
      gen.writeStringField(FIELD_PARTITION_ID, value.partitionId);
      gen.writeNumberField(FIELD_ACCOUNT_ID, value.accountId);
      gen.writeNumberField(FIELD_CONTAINER_ID, value.containerId);
      gen.writeNumberField(FIELD_SIZE, value.size);
      // Optional fields with default values to exclude
      if (value.creationTime > 0) {
        gen.writeNumberField(FIELD_CREATION_TIME, value.creationTime);
      }
      if (value.uploadTime > 0) {
        gen.writeNumberField(FIELD_UPLOAD_TIME, value.uploadTime);
      }
      if (value.deletionTime > 0) {
        gen.writeNumberField(FIELD_DELETION_TIME, value.deletionTime);
      }
      if (value.expirationTime > 0) {
        gen.writeNumberField(FIELD_EXPIRATION_TIME, value.expirationTime);
      }
      if (value.nameSchemeVersion > 0) {
        gen.writeNumberField(FIELD_NAME_SCHEME_VERSION, value.nameSchemeVersion);
      }
      if (value.lifeVersion > 0) {
        gen.writeNumberField(FIELD_LIFE_VERSION, value.lifeVersion);
      }
      // Encryption fields that may or may not apply
      if (value.encryptionOrigin != null && value.encryptionOrigin != EncryptionOrigin.NONE) {
        gen.writeStringField(FIELD_ENCRYPTION_ORIGIN, value.encryptionOrigin.toString());
        if (value.encryptionOrigin == EncryptionOrigin.VCR) {
          gen.writeStringField(FIELD_VCR_KMS_CONTEXT, value.vcrKmsContext);
          gen.writeStringField(FIELD_CRYPTO_AGENT_FACTORY, value.cryptoAgentFactory);
          gen.writeNumberField(FIELD_ENCRYPTED_SIZE, value.encryptedSize);
        }
      }
      gen.writeEndObject();
    }
Default constructor required for Jackson serialization.
ambry-cloud/src/main/java/com/github/ambry/cloud/CloudBlobMetadata.java