0

In Ruby, I have one string like this :

"name":"jucy","id":123,"property":"abc"

I would like to get '123' from the id. what is the easy way to get it? I don't want to create JSON and parse it, it could be a way but too much for this case.

3 Answers 3

3

Load the JSON parser and parse it.

Yes, you thought that would be too much work. It isn't. Why? An extensive JSON library comes with Ruby. The library is probably already loaded. It's very easy to use. It's very fast. It's very flexible, you'll have the whole data structure to work with.

And, most importantly, writing your own parser for balanced delimiters (ie. quotes) is either a lot of work to get right, or too simple and it misses plenty of edge cases like spaces or escapes. This answer and this answer are good examples of that.

The only caveat is your string isn't quite valid JSON, it needs the hash delimiters around it.

require 'json'

almost_json = '"name":"jucy","id":123,"property":"abc"'

my_hash = JSON.parse('{' + almost_json + '}')
puts my_hash["id"]
Sign up to request clarification or add additional context in comments.

Comments

0
'"name":"jucy","id":123,"property":"abc"'[/"id":(\d+),/, 1].to_i

3 Comments

"key\"id":234 or "id": 345.
@NullSoulException Because it doesn't work except for the very specific string the user posted. My previous comment is two examples where it doesn't work, failing to take into account escapes and failing to account for whitespace (oh, thought of another one: "id":123 ,). Finally, Ruby has an easy to use JSON parser which I believe the OP is unaware of, their assumption that parsing it as JSON is hard is wrong, so handing them a half-broken regex is irresponsible.
please provide some kind of explanation too to support your answer.
0

Here are a few ways other than converting the JSON string to a hash.

s = '"name":"jucy","id":123,"property":"abc"'

Regex with a capture group

s[/\"id\":\s*(\d+)/,1]                #=> "123"

Regex with a positive lookbehind

s[/(?<=\"id\":)\d+/]                  #=> "123"

This requires the number of spaces between the colon and first digit to be fixed. I have assumed zero spaces.

Regex with \K (forget everything matched so far)

s[/\"id\":\s*\K\d+/]                  #=> "123"

Find index where id: begins, convert to an integer and back to a string

s[s.index('"id":')+5..-1].to_i.to_s   #=> "123"

Look for digits...

...if, as in your example, the substring is comprised of the only digits in the string:

s[/\d+/]                              #=> "123"

5 Comments

These all have problems. Some of these remember to account for whitespace, some of them do not. Removing the quotes means you cannot differentiate between "id": 123 and "some_id": 123. They all assume the ID will be an integer, one even assumes it's going to be three characters.
@Schwerm, good points. Thanks. Given the example, I think it's reasonable to assume the id is a non-negative integer, but if not, the required changes are straightforward. I made some changes.
Why make such an assumption about the ID? Maybe it becomes a UUID in the future, I've done that. Some are still vulnerable to trivial whitespace changes. They're all vulnerable to escaped quotes like "foo\"id" (I admit that's unlikely, but why risk it?). The last one looking for just digits will fail if there's a key or value before it which contains a number.
@Schwerm, I'm just answering the question. The OP said he/she didn't want to parse the JSON string. The question is not what is the best way to get the id considering that the form of the string might change in future, that there might be different spacing, or what have you. For all we know, it may be a one-off calculation (or 'id' will always be numeric and name and property could never have values containing digits), in which case my last option may be perfectly fine. What if the key id might change to uuid but it's value will remain the only digits in the string?
If you write to the exact spec, or if you make restrictive assumptions, you should at make that clear along with all the caveats. Otherwise you're just being sloppy. Better would be to ask for clarification. Changing keys would break the spec, we were asked to get the value of id, it's qualitatively different then changing values or formatting. As to the JSON parser, a great lesson is to closely examine the client's technical assumptions; in programming, the customer is usually wrong. All in all, this is a great illustration why you don't try to parse JSON with regexes. :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.