简体   繁体   English

Ruby to_yaml将我的json字符串化

[英]Ruby to_yaml stringifies my json

I am trying to convert a ruby hash to yaml. 我正在尝试将ruby hash转换为yaml。 I'd like part of the hash be valid json; 我希望哈希的一部分是有效的json; however, when I try to serialize the json string, it is converted to yaml in quotes. 但是,当我尝试序列化json字符串时,会将其转换为带引号的yaml。

For example, when I just have a simple string, the ouput is as follows (note foo is not in quotations): 例如,当我只有一个简单的字符串时,输出如下(注意foo不在引号中):

request = {}
request['body'] = 'foo'
request.to_yaml # outputs: body: foo

However, when I add something to the beginning of the string, like { foo the output for body gets quoted: 但是,当我在字符串的开头添加一些内容时,例如{ foo ,body的输出将被引用:

request['body'] = '{ foo'
request.to_yaml # outputs: body: '{ foo'

How can I get around this? 我该如何解决? I've tried JSON.parse and, though that make work, I can't be guaranteed that this input will actually be json (could be xml, etc...) -- I just want to give back whatever was given to me but not "stringified". 我已经尝试过JSON.parse ,尽管可以工作,但我不能保证此输入实际上是json(可以是xml等)-我只想退还给我的任何东西但不是“字符串化”。

Basically, I want to give an object that looks like: 基本上,我想给一个看起来像这样的对象:

{ 'request' => {
    'url' => '/posts',
    'method' => 'GET',
    'headers' => [
      'Content-Type' => 'application/json'
    ]
  },
  'response' => {
    'code' => 200,
    'body' => '[{"id":"ef4b3a","title":"this is the title"},{"id":"a98c4f","title":"title of the second post"}]'
  }
}

Which returns: 哪个返回:

request:
    url: /posts
    method: GET
    headers:
        - Content-Type: application/json

response:
    code: 200
    body:
        [{"id":"ef4b3a","title":"this is the title"},{"id":"a98c4f","title":"title of the second post"}]

The reason being: right now, I can go from yaml to the correct ruby hash but I can't go the other way. 原因是:现在,我可以从yaml转到正确的ruby hash,但不能以其他方式使用。

The method my_hash.to_yaml() just takes a hash and converts it to YAML without doing anything special to the values. 方法my_hash.to_yaml()仅获取哈希并将其转换为YAML,而无需对值进行任何特殊处理。 The method does not care whether your string is JSON or XML, it just treats it as a string. 该方法并不关心您的字符串是JSON还是XML,它只是将其视为字符串。

So why is my JSON being put into quotes when other strings aren't? 那么为什么在没有其他字符串的情况下将我的JSON放在引号中呢?

Good question! 好问题! The reason is simple: curly braces are a valid part of YAML syntax. 原因很简单:花括号是YAML语法的有效部分。

This: 这个:

my_key: { sub: 1, keys: 2}

Is called flow mapping syntax in YAML, and it allows you make nested mappings in one line. 在YAML中称为流映射语法,它允许您在一行中进行嵌套映射。 To escape strings which have curly braces in them, YAML uses quotes: 为了转义带有花括号的字符串,YAML使用引号:

my_key: "{ sub: 1, keys: 2}" # this is just a string

Of course, the quotes are optional for all strings: 当然,引号对于所有字符串都是可选的:

my_key: "foo" #same as my_key: foo

Okay, but I want to_yaml() to find my JSON string and convert it to YAML mappings like the rest of the hash. 好的,但是我想to_yaml()找到我的JSON字符串并将其转换为YAML映射,就像其余哈希一样。

Well then, you need to convert your JSON string to a hash like the rest of your hash. 好了,您需要将JSON字符串转换为像其他哈希一样的哈希。 to_yaml() converts a hash to YAML. to_yaml()将哈希转换为YAML。 It doesn't convert strings to YAML. 它不会将字符串转换为YAML。 The proper method for doing this is to use JSON.parse, as you mentioned: 如您所述,执行此操作的正确方法是使用JSON.parse:

request['body'] = JSON.parse( '{"id":"ef4b3a"}' )

But the string might not be JSON! 但是字符串可能不是JSON! It might be XML or some other smelly string. 它可能是XML或其他一些臭字符串。

This is exactly why to_yaml() doesn't convert strings. 就是为什么to_yaml()不转换字符串。 A wise programmer once told me: "Strings are strings. Strings are not data structures. Strings are strings." 一位明智的程序员曾经告诉我:“字符串是字符串。字符串不是数据结构。字符串是字符串。”

If you want to convert a string into a data structure, you need to validate it and parse it. 如果要将字符串转换为数据结构,则需要对其进行验证和解析。 Because there's no guarantee that a string will be valid, it's your responsibility as a programmer to determine whether your data is JSON or XML or just bad, and to decide how you want to respond to each bit of data. 因为不能保证字符串将是有效的,所以作为程序员,您有责任确定您的数据是JSON还是XML或仅是错误的,并决定如何响应数据的每一位。

Since it looks like you're parsing web pages, you might want to consider using the same bit of data other web clients use to parse these things: 由于您似乎在解析网页,因此您可能需要考虑使用其他Web客户端用来解析这些内容的相同数据:

{ 'request' => {
    'url' => '/posts',
    'method' => 'GET',
    'headers' => [
      'Content-Type' => 'application/json' #<== this guy, right here!
    ]
  },
  'response' => {
    'code' => 200,
    'body' => '[{"id":"ef4b3a","title":"this is the title"},{"id":"a98c4f","title":"title of the second post"}]'
  }
}

If the content-type doesn't agree with the body then you should throw an error because your input data is bad. 如果content-typebody不一致,则应输入错误,因为您的输入数据不正确。

The reason '{ foo' requires quote is because this is part of the YAML specification 7.3.3 Plain Style. '{ foo'需要引号的原因是因为这是YAML规范7.3.3纯样式的一部分。

Excerpt 摘抄

Plain scalars must never contain the “: ” and “#” character combinations. 普通标量绝对不能包含“:”和“#”字符组合。 Such combinations would cause ambiguity with mapping key: value pairs and comments. 这种组合将导致映射键(值对和注释)含糊不清。 In addition, inside flow collections, or when used as implicit keys, plain scalars must not contain the “[”, “]”, “{”, “}” and “,” characters. 另外,在内部流集合中,或当用作隐式键时,普通标量不得包含“ [”,“]”,“ {”,“}”和“,”字符。 These characters would cause ambiguity with flow collection structures. 这些字符将与流收集结构产生歧义。

Based on the above even your stated "return" value is incorrect and the body is probably enclosed in single quotes eg 基于上述情况,即使您声明的“返回”值也不正确,并且正文可能用单引号引起来,例如

response:
  code: 200
  body: '[{"id":"ef4b3a","title":"this is the title"},{"id":"a98c4f","title":"title of the second post"}]'

Otherwise it would create ambiguity with "Flow Sequences" ( [ , ] ) and "Flow Mappings" ( { , } ). 否则,它将与“流序列”[] )和“流映射”{} )产生歧义。

If you would like result of the JSON , XML or other notation language to be represented appropriately (read objectively) then you will need to determine the correct parser (may be from the "Content-Type") and parse it before converting it YAML 如果您希望JSONXML或其他表示法语言的结果得到适当的表示(客观地读取),则需要确定正确的解析器(可能来自“ Content-Type”)并进行解析,然后再将其转换为YAML

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM