Salesforce Stack Exchange is a question and answer site for Salesforce administrators, implementation experts, developers and anybody in-between. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I am working on a REST Service that will desiralize the request body and interpret it. My understanding was that calling String.valueOf(objectInstance) would just call objectInstance.toString(). However, I am observing different behavior.

Working

Blob requestBody = Blob.valueOf('[{"key":"value"}]');
List<Object> body = (List<Object>)JSON.deserializeUntyped(requestBody.toString());

Not Working

Blob requestBody = Blob.valueOf('[{"key":"value"}]');
List<Object> body = (List<Object>)JSON.deserializeUntyped(String.valueOf(requestBody));

The above throws:

Line: 11, Column: 1

System.JSONException: Unexpected character ('B' (code 66)): expected a valid value (number, String, array, object, 'true', 'false' or 'null') at input location [1,2]

share|improve this question
up vote 8 down vote accepted

String.valueOf returns Blob[X] for Blob values. I believe it does it this way because System.debug internally uses String.valueOf, and debugging a potentially non-Unicode stream into a Unicode String could break things. In other words, you can't reliably use String.valueOf unless you can also use it in System.debug and get the output you expect. String.valueOf is always safe to use on a Blob, but Blob.toString may result in an exception if the contents are not a Unicode String.

Let's go with some examples to show how other standard and custom objects behave:

String.valueOf(JSON.createParser('[]'));
// JSONParser:[delegate=common.apex.json.ApexJsonParser@7cde3f62]

String.valueOf(Crypto.generateAesKey(128));
// Blob[16]

String.valueOf([SELECT Id FROM Account LIMIT 1]);
// (Account:{Id=001..., RecordTypeId=012...})

String.valueOf(new MyClassWithoutToString());
// or //
new MyClassWithoutToString().toString();
// MyClasswithoutTostring:[key1=value1, key2=value2]

String.valueOf(new MyClassWithToString());
// Hello There. I work correctly because I have an overridden toString.

String.valueOf(Date.today());    Date.today().format()
// 2016-02-10                    // 2/10/2016

Database.getQueryLocator([SELECT Id FROM Account LIMIT 1])
// Database.QueryLocator[Query=SELECT Id FROM Account LIMIT 1]

String.valueOf(Database.setSavepoint());
// SavepointValue0

String.valueOf(new Component.MyCustomComponent());
// *** Crashes and produces no logs ***

As you can see, you can never quite be sure what you're going to get out of it, unless you're using one of the concrete types listed in the documentation, which is currently: Date, DateTime, Decimal, Integer, and Long.

It does say that it supports "Object" generically, but generally speaking, you'll get the "debug safe" version of a string if you do so, which means it will probably be the wrong value.

share|improve this answer
    
Whoa. This is fantastic to know. puts like behavior from String.valueOf for in page debug statements, yes please! – Christian Carter Feb 11 at 4:08

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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