{"action":"created","issue":{"url":"https://api.github.com/repos/jmoiron/sqlx/issues/135","labels_url":"https://api.github.com/repos/jmoiron/sqlx/issues/135/labels{/name}","comments_url":"https://api.github.com/repos/jmoiron/sqlx/issues/135/comments","events_url":"https://api.github.com/repos/jmoiron/sqlx/issues/135/events","html_url":"https://github.com/jmoiron/sqlx/issues/135","id":69095519,"number":135,"title":"MapScan and SliceScan string conversion pain point","user":{"login":"johnleegrant","id":5324735,"avatar_url":"https://avatars.githubusercontent.com/u/5324735?v=3","gravatar_id":"","url":"https://api.github.com/users/johnleegrant","html_url":"https://github.com/johnleegrant","followers_url":"https://api.github.com/users/johnleegrant/followers","following_url":"https://api.github.com/users/johnleegrant/following{/other_user}","gists_url":"https://api.github.com/users/johnleegrant/gists{/gist_id}","starred_url":"https://api.github.com/users/johnleegrant/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/johnleegrant/subscriptions","organizations_url":"https://api.github.com/users/johnleegrant/orgs","repos_url":"https://api.github.com/users/johnleegrant/repos","events_url":"https://api.github.com/users/johnleegrant/events{/privacy}","received_events_url":"https://api.github.com/users/johnleegrant/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":1,"created_at":"2015-04-17T08:36:36Z","updated_at":"2015-04-17T16:27:07Z","closed_at":null,"body":"In the same way Get and Select semantics have been introduced for Scan and StructScan, I'm wondering if something similar could be added for MapScan and SliceScan. It's so useful to be able to go from a SQL statement to JSON via MapScan - example use case would be dynamic pivot queries. I find I need to use the following code to make the sqlx alternate scan types useful - MapBytesToString is necessary to prevent json.Marshal from returning Base64 instead of strings. This doesn't feel right to me. There must be a more, erm, idiomatic way to achieve this and may be it could be included as part of the core sqlx package?\r\n\r\n```go\r\npackage sqlxx\r\n\r\nimport \"github.com/jmoiron/sqlx\"\r\n\r\nfunc MapBytesToString(m map[string]interface{}) {\r\n\tfor k, v := range m {\r\n\t\tif b, ok := v.([]byte); ok {\r\n\t\t\tm[k] = string(b)\r\n\t\t}\r\n\t}\r\n}\r\n\r\nfunc MapScan(r sqlx.ColScanner, dest map[string]interface{}) error {\r\n\terr := sqlx.MapScan(r, dest)\r\n\tif err != nil {\r\n\t\treturn err\r\n\t}\r\n\tMapBytesToString(dest)\r\n\treturn nil\r\n}\r\n\r\nfunc SliceBytesToString(s []interface{}) {\r\n\tfor k, v := range s {\r\n\t\tif b, ok := v.([]byte); ok {\r\n\t\t\ts[k] = string(b)\r\n\t\t}\r\n\t}\r\n}\r\n\r\nfunc MapSlice(r sqlx.ColScanner) ([]interface{}, error) {\r\n\ts , err := sqlx.SliceScan(r)\r\n\tif err != nil {\r\n\t\treturn nil, err\r\n\t}\r\n\tSliceBytesToString(s)\r\n\treturn s, nil\r\n}\r\n```"},"comment":{"url":"https://api.github.com/repos/jmoiron/sqlx/issues/comments/94021281","html_url":"https://github.com/jmoiron/sqlx/issues/135#issuecomment-94021281","issue_url":"https://api.github.com/repos/jmoiron/sqlx/issues/135","id":94021281,"user":{"login":"jmoiron","id":218132,"avatar_url":"https://avatars.githubusercontent.com/u/218132?v=3","gravatar_id":"","url":"https://api.github.com/users/jmoiron","html_url":"https://github.com/jmoiron","followers_url":"https://api.github.com/users/jmoiron/followers","following_url":"https://api.github.com/users/jmoiron/following{/other_user}","gists_url":"https://api.github.com/users/jmoiron/gists{/gist_id}","starred_url":"https://api.github.com/users/jmoiron/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/jmoiron/subscriptions","organizations_url":"https://api.github.com/users/jmoiron/orgs","repos_url":"https://api.github.com/users/jmoiron/repos","events_url":"https://api.github.com/users/jmoiron/events{/privacy}","received_events_url":"https://api.github.com/users/jmoiron/received_events","type":"User","site_admin":false},"created_at":"2015-04-17T16:27:07Z","updated_at":"2015-04-17T16:27:07Z","body":"For a little history, this used to scan directly to the `sql.NullString` type and use `string` if Valid was true, but I got a bug report saying that `lib/pq` refused to scan `time.Time` into a string.  I realized that my only reliable choice was to use `interface{}`.  There are two problems with this proposal:\r\n\r\n* it's subtle, potentially breaking behavior\r\n* not all `[]byte` are valid `string`\r\n\r\nI am actually okay with 1 if it weren't for 2, but that makes this incredibly unlikely.  If you are scanning `bytea` type in PostgreSQL with SliceScan, some may be `[]byte` and some `string`, depending on their *contents*.  I think this is unacceptable behavior.  If you have heterogeneous data you're scanning into a `[]interface{}`, then only *your* app will know how to properly deal with that;  there isn't a decision sqlx can make that will work.  It's at this point that I recommend using a `struct`.\r\n\r\nI would rather sqlx be 100% reliable and do something slightly inconvenient 90% of the time than be 90% convenient and 10% unreliable.\r\n\r\nStill, I know that `MapScan` and `SliceScan` can be frustrating to people, and that you cannot always define structs for all your SQL result sets.  You're [not the first one](https://github.com/jmoiron/sqlx/issues/80#issuecomment-76088110) to say that the usefulness of MapScan and SliceScan is reduced because of this.  I suspect the half-way for many people will be to change `SliceScan` to use outparams and to finally fix #80.  \r\n\r\nThis would mean that you could pass `map[string]string` to MapScan and `[]string` to SliceScan, and deal with the fallout of that as you need to, even from sql eg, many people complain about NULL but you can use COALESCE to ensure empty string instead of NULL if that's actually a valid thing to do for your data model."}}