mirror of
https://github.com/doctrine/orm.git
synced 2026-03-24 06:52:09 +01:00
$connection->quote() converts JSON into String #5933
Reference in New Issue
Block a user
Delete Branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Originally created by @yurtesen on GitHub (Mar 26, 2018).
Originally assigned to: @Ocramius on GitHub.
I am trying to use
executeUpdate()on PostgreSQL 9.6 with Doctrine 2.6 with Symfony3 on a jsonb column.The problem is that when I use
$connection->quote()function, withType::JSONit seems to convert whole JSON to a string. Documentation is not very clear on what it should be doing . I understood from documentation that it should result in valid JSON, no? is this a bug?Results:
"{\"name\": \"product\"}"@Ocramius commented on GitHub (Mar 26, 2018):
Pass in ['name'=>'product']
On Mon, 26 Mar 2018, 18:42 yurtesen, notifications@github.com wrote:
@yurtesen commented on GitHub (Mar 26, 2018):
But that is not JSON? Isn't the type should represent the input type?
I tried this
print $connection->quote("['name'=>'product']",Type::STRING);which prints'[''name''=>''product'']'@Ocramius commented on GitHub (Mar 26, 2018):
Ah, I see you are using quoting: missed that.
You really want parameter binding.
The conversion of the value is done by DBAL, so if you pass in a PHP array you get a json array (or hashmap), if you pass in a string then a json string and so on.
@yurtesen commented on GitHub (Mar 26, 2018):
I wanted to use parameter binding but I am using jsonb_set in PostgreSQL and trying to build the query ends up with an error
Error: Expected known function, got 'jsonb_set'" atIf I use native query then doctrine/postgresql does not recognize all parameters. I have a query like this
UPDATE cart c SET data = jsonb_set( coalesce(data,'{"product": {}}'), '{"product",":id"}','{"name":":name"}') WHERE cart.id = :cart';it does not recognize:idand:nameare parameters, only the:cartparameter is replaced in final query.So as a last resort, I had to go totally low level. Now I figured out this works with
json_decode()$connection->quote(json_decode('{"name": "product"}'), Type::JSON);Not sure if this makes sense at all or improve security (eg. against sql injection) at all in cases where name
"product"is given online by users?Also shouldn't the
quote()function work with JSON as string?@Ocramius commented on GitHub (Mar 27, 2018):
Quoting will do the type conversion. A string and a hashmap are very different things, so you need to pass in the correct data structure to be quoted as a value.
@yurtesen commented on GitHub (Mar 27, 2018):
I didn't quote understand exactly what you mean. I was also not sure of what you meant earlier when you said "you are using quoting". You mean the
quote()function?I am giving in a standard json object. Isn't a json object technically a string and also consist of key/value pairs so a hash map?
Let me ask it in a more direct way. I feel like I am doing something wrong. Lets say I have the json object
{ "name":"John", "age":30, "car":null }and I am about to assign it to ajsonbfield. What is the correct way to pass this to$connection->quote()function for quoting?@Ocramius commented on GitHub (Mar 27, 2018):
A string is a string, a key/value map is a key/value map. Doctrine converts what you have in memory. If what you have in memory is a string, you will store a JSON string, not a JSON object.
@yurtesen commented on GitHub (Mar 27, 2018):
Sorry, but that really did not make things clear at all :( also did not quite answer my question.
The definition of JSON. ->
JavaScript Object Notation (JSON) is a lightweight, text-based, language-independent data interchange format<- notice text-based, if it is not text, it is not JSON.Can you give an example to a JSON object, with PHP code, which is NOT a string? Keep in mind, it is not a JSON object if it is a PHP object or associative array. I am trying to understand what you mean, perhaps the most direct way is with a code example?
@Ocramius commented on GitHub (Mar 27, 2018):
Yes:
This is the difference here. If you pass around a
string, PHP (and DBAL) will interpret it as astring. If you pass around an object (or anything compatible withjson_serialize()) then you will get a JSON-object saved in your DB value.Doctrine DBAL performs a
json_encode()on its own.@yurtesen commented on GitHub (Mar 27, 2018):
@Ocramius your
$jsonObjectis a PHP object. json_decode() manualTakes a JSON encoded string and converts it into a PHP variable.also saysReturns the value encoded in json in appropriate PHP type..PHP converts JSON Object into PHP stdClass() object. So your
$jsonObjectvariable has nothing to do with JSON. Yes, your code prints outobjectas type, but it is the PHP object type. Same result will be from:The
$stdObjectis also NOT a JSON object.When I pass the
JSON encoded stringtoquote()I clearly tell it that it is JSON$connection->quote('{"name": "product"}', Type::JSON);yet, it screws it up. Actually, on the contrary, if I tell it isType::STRINGthen it actually returns'{"product","name"}'which is correct. I would say this is a bug.Also from Doctrine json type manual entry.
If you know that the data to be stored always is in a valid UTF-8 encoded JSON format string, you should consider using this type.Well my data is a valid JSON string!?Anyway, thanks for your time. But I won't dwell on this further...time constraints... :(
@Ocramius commented on GitHub (Mar 27, 2018):
@yurtesen I've already explained it in the best way I can. Strings are strings: objects are objects. A json string is still a string: trying to encode it as json leads to double-encoding.