在Matlab结构体的字段名中使用句号

3

我正在使用webwrite发布到一个API。我想要设置的JSON对象中的一个字段名称是odata.metadata。我正在创建一个类似于以下结构的JSON对象:

json = struct('odata.metadata',metadata,'odata.type',type,'Name',name);

但是我收到了一个错误信息。

  Error using struct
  Invalid field name "odata.metadata"

这是我在Matlab中尝试使用的JSON对象。出于简单起见,所有字符串都如下所示:
{
    "odata.metadata": "https://website.com@Element",
    "odata.type": "Blah.Blah.This.That",
    "Name": "My Object"
}

有没有办法提交这个JSON对象,还是说这是一个无解的问题?


假设API能够像这样工作 - 也许您可以通过在最顶层的JSON对象中具有一个名为odata的字段来包含另一个带有metadatatype字段的JSON对象,从而完全避免此问题。 - Dev-iL
只是为了明确,我没有制作API,也无法控制所有者如何实现它。 - toshiomagic
我并没有说你需要改变API,只是看看它是否能够使用嵌套的JSON对象。 - Dev-iL
1
我只希望MathWorks停止使用“.”作为许多完全不同的操作,这些操作目前都是有效的。不仅不应该有任何运算符(例如.*),结构、单元格等名称分隔符也应该是一些不同的符号(例如R使用@$)。当数字时,“.”是十进制分隔符,否则应该是字符串中的有效字符。就是这样。(双关语) - Carl Witthoft
3个回答

2
字段名不允许有点。原因是这会被误解为在结构体本身内访问另一个嵌套结构。比如,执行json.odata.metadata会被解释为json是一个struct,含有一个成员的字段名是odata,并且odata还有一个成员的字段名是metadata。这将不会被解释为一个具有组合字段名odata.metadata的成员。您需要将字段重命名为其他名称或稍微更改字段名称的约定。通常的约定是用下划线替换点。如果您不想手动重命名字段名,自动处理这个问题的方法是使用一个称为matlab.lang.makeValidName的函数,该函数接收一个字符串并将其转换为有效的字段名。此函数是在R2014a中引入的。对于旧版本,它称为genvarname
例如:
>> matlab.lang.makeValidName('odata.metadata')

ans =

odata_metadata

因此,要消除歧义,可以将所有点替换为_,或使用matlab.lang.makeValidNamegenvarname来为您处理。

2
我建议您使用containers.Map而不是struct来存储数据,然后通过迭代Map字段名并将其与数据一起附加到JSON中来创建JSON字符串。
这是一个快速演示:
%// Prepare the Map and the Data:
metadata = 'https://website.com@Element';
type = 'Blah.Blah.This.That';
name = 'My Object';
example_map = containers.Map({'odata.metadata','odata.type','Name'},...
                             {metadata,type,name});
%// Convert to JSON:
JSONstr = '{'; %// Initialization
map_keys = keys(example_map);
map_vals = values(example_map);
for ind1 = 1:example_map.Count
  JSONstr = [JSONstr '"' map_keys{ind1} '":"' map_vals{ind1} '",'];
end

JSONstr =[JSONstr(1:end-1) '}']; %// Finalization (get rid of the last ',' and close)

这将产生一个有效的JSON字符串。
显然,如果您的值不是字符串,则需要使用num2str等进行转换。
另一种选择是考虑JSONlab FEX提交。我看到它的savejson.m能够接受单元数组 - 可以保存任何您喜欢的字符串。
其他选择可能包括任何您可以从MATLAB调用的众多Java或Python JSON库。

1
我可能不应该将这个作为答案加入 - 但是你可以在结构体字段名中使用 '.'...
在我进一步解释之前 - 我并不支持这样做,它几乎肯定会导致错误和很多麻烦... @rayryeng 的方法是更好的选择。
如果您的结构体是由一个创建包含 "." 的字段的 mex 函数创建的 - > 那么您将得到您想要的结果。
要创建自己的测试,请参见 Mathworks 示例 并进行修改。
(我不会在这里放置完整的代码以防止这种做法。)
如果您更新 char 示例并编译测试_mex,则会获得:
>> obj = test_mex

obj = 

       Doublestuff: [1x100 double]
    odata.metadata: 'This is my char'

注意:您只能使用动态字段名在 Matlab 中访问自定义字段。
obj.('odata.metadata')

您需要使用 mex 功能来更新它...


哇...我想我错了...使用MEX去做这个哈哈。非常好。+1。 - rayryeng

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接