这个问题试图以一种与语言无关的方式收集关于不同语言和YAML实现的问题的信息。
假设我有一个像这样的YAML文件:
first:
- foo: {a: "b"}
- "bar": [1, 2, 3]
second: | # some comment
some long block scalar value
我想将这个文件加载到本机数据结构中,可能更改或添加一些值,然后再次转储。但是,当我转储它时,原始格式将不被保留:
前言:在整个回答中,我提到了一些流行的YAML实现。这些提及并不是详尽无遗的,因为我并不了解所有的YAML实现。
我将对数据结构使用YAML术语:原子文本内容(偶数)是一个标量。项序列,在别处称为数组或列表,是序列。键值对的集合(在别处称为字典或哈希)是一种映射。
如果您使用的是Python,请考虑使用ruamel(可能是从PyYAML切换过来的),因为它实现了到本机结构的往返,所以这个答案并不适用于它。
另一方面,注释会很快被丢弃,因为它们不属于事件或节点(这里的例外是ruamel,它将注释链接到下面的事件)。一些YAML实现(libyaml,SnakeYAML)提供了对令牌流的访问,令牌流甚至比事件树更低级。这个令牌流确实包含注释,但是它只能用于执行语法突出显示之类的操作,因为API不包含用于再次使用令牌流的方法。
如果只需要加载YAML文件,然后再次转储它,请使用实现的一个较低级别的API,只加载YAML直到表示(节点图)或序列化(事件树)级别。要搜索的API函数分别是compose/parse和serialize/present。
最好使用事件树而不是节点图,因为一些实现在组合时已经忘记了映射键的原始顺序(由于内部使用了hashmaps)。例如,这个问题详细说明了使用SnakeyAML加载/转储事件。
"1 \x2B 1"
在解析转义序列后,此加载作为字符串“1+1”
。即使在事件流中,关于转义序列的信息在我所知道的所有实现中都已经丢失了。事件只记得它是一个双引号标量,因此回写它将导致:
"1 + 1"
类似地,折叠的块标量(以开头)通常不会记住原始输入中的换行符在哪里折叠成了空格字符。
因此,总而言之,加载到事件树并再次转储通常会保留:
如果使用节点图而不是事件树,则可能还会丢失映射中的键顺序。有些API(如go-yaml)不提供对事件树的访问,因此您别无选择,只能改用节点图。
如果您希望修改数据并保留原始格式,则需要在不将数据加载到本机结构的情况下对数据进行操作。这通常意味着您对标量、序列和映射进行操作,而不是像您可能习惯的对字符串、数字、列表或目标编程语言提供的任何结构进行操作。
在任何情况下,您都需要了解一点关于YAML类型解析的知识,以便正确处理给定的数据。当您将YAML文件加载到声明的本机结构中时(在具有静态类型系统的语言中很常见,例如Java或Go),如果可能的话,YAML处理器将把YAML结构映射到它。但是,如果没有给出目标类型(在像Python或Ruby这样的脚本语言中很典型,但在Java中也有可能),则从节点内容和样式推导出类型。
由于我们不使用本机加载,因为我们需要保留格式信息,因此将不执行此类型解析。但是,您需要了解它在两种情况下是如何工作的:
42
的标量,并且需要知道它是字符串还是整数。“42”
,则必须确保以后不会将其作为整数42
加载。我不在这里讨论所有的细节;在大多数情况下,只要知道如果一个字符串被编码为标量,但看起来像其他东西(例如一个数字),那么您应该使用带引号的标量就足够了。
根据您的实现,您可能会接触到YAML标记。很少在YAML文件中使用(它们看起来像!!str
、!!map
、!!int
等等),它们包含关于节点的类型信息,可以在具有异构数据的集合中使用。更重要的是,YAML定义了所有没有显式标记的节点都将被分配一个作为类型解析的一部分。这可能在节点图级别已经发生,也可能没有发生。因此,在节点数据中,即使原始节点没有节点标记,也可以看到节点的标记。
以两个感叹号开头的标记实际上是简写,例如!!str
是tag:yaml.org,2002:str
的简写。您可能在您的数据中看到这两种情况,因为实现处理它们的方式完全不同。
对您来说重要的是,当您创建节点或事件时,您可能能够并且也可能需要分配一个标记。如果不希望输出包含显式标记,则使用非特定标记!
表示非纯标量,使用?
表示事件级别上的其他所有内容。在节点级别上,请参考实现的文档,了解是否需要提供解析的标记。如果不是,则适用与非特定标记相同的规则。如果文档中没有提到它(很少提到),就尝试一下。
总而言之:通过加载事件树或节点图来修改数据,在所获得的数据中添加、删除或修改事件或节点,然后将修改后的数据再次显示为YAML。根据您想要做什么,它可能会帮助您创建您想要添加到YAML文件中的数据作为本机结构,将其序列化到YAML中,然后作为节点图或事件树再次加载。从那里,您可以将它包含在您想要修改的YAML文件的结构中。
YAML尚未设计用于此任务。事实上,它被定义为一种序列化语言,假设您的数据是以某种编程语言的原生数据结构编写的,并从那里转储到YAML。然而,实际上,YAML被大量用于配置,这意味着您通常手工编写YAML并将其加载到本机数据结构中。
这种对比就是为什么在保留格式的同时修改YAML文件如此困难的原因:YAML格式已经被设计为瞬态数据格式,由一个应用程序编写,然后由另一个(或相同的)应用程序加载。在这个过程中,保留格式并不重要。但是,对于签入到版本控制的数据(您希望diff只包含实际更改过的数据行),以及手工编写YAML的其他情况,因为您希望保持样式一致,则可以这样做。
对于只更改给定YAML文件中的一个数据项而保持其他所有内容不变,没有完美的解决方案。加载一个YAML文件并不是给你一个YAML文件的视图,而是给你它所描述的内容。因此,所有不属于所描述内容的部分--最重要的是,注释和空白--都极难保存。
如果格式保存对您很重要,并且您不能忍受这个答案中的建议所作的折衷,那么YAML不是适合您的工具。
我使用setUserVisibleHint()方法加载数据,但是这个方法在oncreateview之前调用,所以我得到的是NPE。 我已经检查了从下面提到的链接堆栈溢出的索洛。 请帮我做这个。我总共有5个碎片。在每个片段中,我都在fragment的onCreateView方法中进行服务器调用。
我有一个要求,在editbox中输入文本后,单击虚拟键盘完成(EditorInfo.IME\u ACTION\u DONE),现在光标不可见[我使用的是editText.setCursorVisible(false)]。现在问题是我再次单击编辑框光标不可见,但文本进入编辑框。 谢谢
我尝试使用以下代码(使用usermodel)写入新的Excel文件 然后,我使用了相同的文件并尝试使用下面的代码使用eventmodel读取。它给出了错误: 线程“main”org.apache.poi.openxml4j.exceptions中出现异常。InvalidFormatException:包应包含位于org.apache.poi.openxml4j.opc.ZipPackage.get
我正试图按照HTML5数字输入中的建议将输入数字格式化为两个小数--总是显示两个小数位,但它破坏了撤消输入的可能性。 键入一个数字,然后移除焦点,它将变为所需的格式。但是您不能按ctrl-Z返回。
$('modal#u narasi')。模态('show');//完成加载$('.modal title')时显示引导模式。文本(“编辑Perusahaan Baik”);//将标题设置为引导模式标题},错误:函数(jqXHR,textStatus,errorshown){alert('error get data from ajax');});
问题内容: 这是我执行此操作的代码` 问题答案: 变量名称不应以大写字母开头。应该是。 重写JTable 的方法,而不是TableModel的方法。