Why the content is not being respected
And it's not just add_post_meta()
, but any functions like add_term_meta()
and add_user_meta()
that uses add_metadata()
.
And the reason why the value gets serialized again is because add_metadata()
will automatically serialize the meta value using maybe_serialize()
which (unfortunately) will serialize the value even if it's already serialized.
How to tackle the issue
In your case, if possible, pass an array instead of the serialized value/string:
// A non-scalar value will be automatically serialized by maybe_serialize().
$value = array( 'noindex', 'nofollow' );
add_post_meta( get_the_ID(), 'robots', $value, true );
However, if you retrieved/received the value from somewhere and you need to retain its exact format when saving, then — as you've already figured it out — you'll need to unserialize the value before passing it to add_post_meta()
to prevent the double serialization.
But in WordPress, instead of using the native unserialize()
function in PHP, I suggest you to use maybe_unserialize()
instead:
$value = 'a:2:{i:0;s:7:"noindex";i:1;s:8:"nofollow";}';
// Unserialize the value and pass it to add_post_meta().
add_post_meta( get_the_ID(), 'robots', maybe_unserialize( $value ), true );