统一解析json文件[重复]
Posted
技术标签:
【中文标题】统一解析json文件[重复]【英文标题】:parsing json file in unity [duplicate] 【发布时间】:2021-07-14 15:30:30 【问题描述】:我无法在 Unity 中解析 JSON。这是 JSON 文件:
"play_classic": [
"english": "PLAY CLASSIC" ,
"spanish": "JUEGO CLÁSICO" ,
"portuguese": "JUEGO CLÁSICO" ,
"russian": "IGRAT' V KLASSICHESKUYU"
]
结构和代码如下所示:
[System.Serializable]
class Root
public List<PlayClassicData> play_classic get; set;
[System.Serializable]
class PlayClassicData
public string english get; set;
public string spanish get; set;
public string portuguese get; set;
public string russian get; set;
实现如下所示:
ParseJson
类:
public void Deserialize()
string path = Application.dataPath + "path...";
using (StreamReader r = new StreamReader(path))
string json = r.ReadToEnd();
Root classic = JsonUtility.FromJson<Root>(json);
//Root classic = JsonConvert.DeserializeObject<Root>(json);
Debug.Log("english:" + classic.play_classic[0].english);
Debug.Log("spanish:" + classic.play_classic[0].spanish);
代码抛出错误:
NullReferenceException: Object reference not set to an instance of an object
Assets.Scripts.Infastructure.PARSER.ParseJson.Deserialize () (at Assets/Scripts/Infastructure/PARSER/ParseJson.cs:23)
【问题讨论】:
我没有添加整个代码。 您可能不想在这里使用内置的JsonUtility
,而是使用例如Newtonsoft .NET JSON
-> 它支持(de)serialization of Dictionary,因此您实际上可以拥有public Dictionary<string, string> play_classic = new Dictionary<string, string>();
,并且可以轻松地在您的JSON文件中动态扩展它...
另外 JsonUtility 不支持属性 .. 你想通过删除所有 get; set
来使用字段
【参考方案1】:
这里有两个问题。
-
错误的
Root
。应该是public List<PlayClassicData> play_classic get; set;
索引。 classic._playClassicData[0].spanish
为空。这是具有西班牙语值的第二个元素:classic._playClassicData[1].spanish);
固定Root
:
class Root
public List<PlayClassicData> play_classic get; set;
演示:
var json = File.ReadAllText("example1.json");
var o = JsonSerializer.Deserialize<Root>(json);
Console.WriteLine(o.play_classic[0].english);
Console.WriteLine(o.play_classic[1].spanish);
打印出来:
PLAY CLASSIC
JUEGO CLÁSICO
我使用了System.Json.Text.JsonSerializer
,但使用JsonConvert.DeserializeObject<Root>(json);
结果是一样的。
【讨论】:
我改了还是一样的错误 一个。json
是否有预期的文本?湾。 JsonUtility.FromJson
这就是您的空异常所在的位置。使用JsonConvert.DeserializeObject<Root>(json)
。
它只适用于 JsonConvert.DeserializeObjectSystem.Json.Text.JsonSerializer
在使用 .Net Framework 4.x
的 Unity 中不可用,Unity 的内置 JsonUtility 并且通常序列化程序不支持属性。您想通过删除 get; set;
将它们转换为字段【参考方案2】:
我将假设 Json 是多语言翻译的表示。并且可以在返回中翻译多个句子/标签。
而且您不希望为play_classic
和play_hard
提供一个具有相同语言属性的类。特别是如果添加一种语言会迫使您在前端和每个类中添加一个属性。
"play_classic": [
"english": "PLAY CLASSIC" ,
"spanish": "JUEGO CLÁSICO" ,
"portuguese": "JUEGO CLÁSICO" ,
"russian": "IGRAT' V KLASSICHESKUYU"
],
"play": [
"english": "PLAY" ,
"spanish": "JUEGO" ,
"portuguese": "JUEGO" ,
"russian": "IGRAT'"
],
"classic": [
"english": "CLASSIC" ,
"spanish": "CLÁSICO" ,
"portuguese": "CLÁSICO" ,
"russian": "KLASSICHESKUYU"
]
我将选择Dictionary<string, List<Dictionary<string, string>>>
作为目标对象。并且会将内部列表弄平,例如:Dictionary<string, Dictionary<string, string>>
.
注意:由于内置的JsonUtility
不支持字典,因此您必须另外将Newtonsoft .Net JSON
安装/导入到您的项目中。
derHugo评论,用户:7111561
var resultRaw = JsonConvert.DeserializeObject<Dictionary<string, List<Dictionary<string, string>>>>(input);
var resultFlattern = resultRaw.ToDictionary(
x => x.Key,
x=> x.Value.SelectMany(trd=> trd)
.ToDictionary(kvp=> kvp.Key, kvp=> kvp.Value)
);
用法:给定按钮 play_classic 和语言“葡萄牙语”
直接访问将非常简单
resultFlattern[buttonName][language]
var buttonName="play_classic"; var language= "portuguese";
if(resultFlattern.TryGetValue(buttonName, out Dictionary<string, string> allTrads))
if(allTrads.TryGetValue(language, out string traduction))
Console.WriteLine($"Traduction for button [buttonName] in [language] is : [traduction]") ;
else
Console.WriteLine($"Cant find tanslation for button : [buttonName] in [language]") ;
else
Console.WriteLine($"Cant find tanslation for button : [buttonName]");
演示:https://dotnetfiddle.net/FcxtUp
我将把它包装成一个只加载一次所有翻译的好帮手。并给出给定语言和按钮/标签的翻译。当没有找到翻译时,我还将使用默认返回标签名称来防火。
如果语言不是一件容易的事情,你可以再一次改变结果,只在Dictionary<string, string>
中保留一份翻译。标签名称/翻译
【讨论】:
很好的例子和解决方案。 请注意,为此您必须另外安装/导入Newtonsoft .Net JSON
到您的项目中,因为内置的JsonUtility
不支持Dictionary
;) .. 一般请注意,为此虽然.CSV
的使用更方便;)
@derHugo,在 OP 代码中有一个 JsonConvert.DeserializeObject<Root>(json);
,并且 Op 有一条评论,例如“它只适用于 JsonConvert.DeserializeObject<Root>
...这是统一的”。我认为它是可用的。
将您的评论添加到答案中,并注明出处。
@Self 哦,没注意到。我的立场已得到纠正;)似乎 OP 已经这样做了(或者 Unity 在较新版本中默认导入该包)【参考方案3】:
您的 Json 与您的数据不匹配
public PlayClassicData[] _playClassicData get; set;
应该是:
public List<PlayClassic> play_classic get; set;
所以classic._playClassicData
是探测null
编辑:
正如 derHugo 指出的那样:
Unity 的内置 JsonUtility 不支持属性。您想通过删除所有 get; set;
来使用字段
应该是:
public List<PlayClassic> play_classic;
【讨论】:
我添加了列表而不是数组相同的错误没有任何改变。 不仅列表和数组不同,而且属性上的名字和json中的名字不匹配 我再次更改了列表的名称同样的错误。 Unity 的内置 JsonUtility 不支持属性。您想通过删除所有get; set;
来使用字段以上是关于统一解析json文件[重复]的主要内容,如果未能解决你的问题,请参考以下文章