统一解析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&lt;string, string&gt; play_classic = new Dictionary&lt;string, string&gt;();,并且可以轻松地在您的JSON文件中动态扩展它... 另外 JsonUtility 不支持属性 .. 你想通过删除所有 get; set 来使用字段 【参考方案1】:

这里有两个问题。

    错误的Root。应该是public List&lt;PlayClassicData&gt; 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&lt;Root&gt;(json); 结果是一样的。

【讨论】:

我改了还是一样的错误 一个。 json 是否有预期的文本?湾。 JsonUtility.FromJson 这就是您的空异常所在的位置。使用JsonConvert.DeserializeObject&lt;Root&gt;(json) 它只适用于 JsonConvert.DeserializeObject...这是统一的 请注意 System.Json.Text.JsonSerializer 在使用 .Net Framework 4.x 的 Unity 中不可用,Unity 的内置 JsonUtility 并且通常序列化程序不支持属性。您想通过删除 get; set; 将它们转换为字段【参考方案2】:

我将假设 Json 是多语言翻译的表示。并且可以在返回中翻译多个句子/标签。 而且您不希望为play_classicplay_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&lt;string, List&lt;Dictionary&lt;string, string&gt;&gt;&gt; 作为目标对象。并且会将内部列表弄平,例如:Dictionary&lt;string, Dictionary&lt;string, string&gt;&gt;. 注意:由于内置的​​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&lt;string, string&gt; 中保留一份翻译。标签名称/翻译

【讨论】:

很好的例子和解决方案。 请注意,为此您必须另外安装/导入Newtonsoft .Net JSON 到您的项目中,因为内置的JsonUtility 不支持Dictionary ;) .. 一般请注意,为此虽然.CSV 的使用更方便;) @derHugo,在 OP 代码中有一个 JsonConvert.DeserializeObject&lt;Root&gt;(json);,并且 Op 有一条评论,例如“它只适用于 JsonConvert.DeserializeObject&lt;Root&gt;...这是统一的”。我认为它是可用的。 将您的评论添加到答案中,并注明出处。 @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文件[重复]的主要内容,如果未能解决你的问题,请参考以下文章

统一读取和解析 C# 中的 Json 文件

解析大型 JSON 文件 [重复]

解析csv文件中的json字符串[重复]

在 Swift 中使用动态键解析 JSON [重复]

下载 JSON 文件,但解析显示不可读的字符 [重复]

如何在统一 C# 中解析来自 JSON 的数据? [复制]