反序列化Minecraft json的更好方法 [英] Better way to deserialize Minecraft json

查看:105
本文介绍了反序列化Minecraft json的更好方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用来自(Minecraft json > 1.8.json下载)。一个示例:

I am trying to work with Minecraft json from (1.8.json download). A Sample:

{
  "objects": {
    "realms/lang/de_DE.lang": {
      "hash": "729b2c09d5c588787b23127eeda2730f9c039194",
      "size": 7784
    },
    "realms/lang/cy_GB.lang": {
      "hash": "7b52463b2df4685d2d82c5d257fd5ec79843d618",
      "size": 7688
    },
    "minecraft/sounds/mob/blaze/breathe4.ogg": {
      "hash": "78d544a240d627005aaef6033fd646eafc66fe7a",
      "size": 22054
    },
    "minecraft/sounds/dig/sand4.ogg": {
      "hash": "37afa06f97d58767a1cd1382386db878be1532dd",
      "size": 5491
    }
  }
}

实际的json更长,大约2940行。

The actual json is much longer, some 2940 lines.

我需要一种反序列化的方法,它并不完全是疯狂的-使用JSONUtils,我得到4411行代码,但同一代码不能用于其他版本的Minecraft。

I need a way to deserialize this that isn't completely insane - using JSONUtils I get 4411 Lines of Code, but the same code can't be used for any other version of Minecraft.

推荐答案

自动化工具可能非常有用,但并不完美-尤其是在字典方面。

The automated tools can be very useful, but they are not perfect - especially when it comes to dictionaries.

首先要注意的是,结构与它们都是由 hash size 属性组成。这意味着我们可以一遍又一遍地使用同一类,而不必创建数百个相同的类:

The first thing to note is that the structure is the same for all of them, that is they all consist of hash and size properties. This means rather than creating hundreds of identical classes we can use the same one over and over:

' the type that repeats from your robot:
Public Class MinecraftItem
    Public Property hash As String
    Public Property size As Int32
End Class

由于自动化工具在运行中(它们不会向前看或向后看),因此它们不会真的不知道它们都是一样的。接下来的事情是,在这种情况下,机器人生成的类将无法工作:

Since the automated tools are working on the fly (they do not look ahead...or back) they don't really know that they are all the same. The next thing is that the classes the robots generate wont work in this case:

Public Property minecraft/sounds/music/game/creative/creative3.ogg As _
            MinecraftSoundsMusicGameCreativeCreative3Ogg

作为属性名称是非法的。但是,这些名称可以用作Dictionary键。除了上述 MinecraftItem 类外,我们可能还需要一个容器类:

That is illegal as a property name. However, the names will work just fine as Dictionary keys. In addition to the above MinecraftItem class, we might want a container class:

Public Class MinecraftContainer
    Public objects As Dictionary(Of String, MinecraftItem)
End Class

至少有3种获取数据的方法:

There are (at least) 3 ways to get at the data:

Imports Newtonsoft.Json
Imports Newtonsoft.Json.Linq

Dim jstr As String = ...from whereever

' parse the json into a JObject
Dim js As JObject = JObject.Parse(jstr)

' if you somehow know the names, you can pluck out the data:
Dim mi = js("objects")("minecraft/sounds/mob/blaze/hit2.ogg")

Console.WriteLine(mi("hash").ToString & "    " & mi("size").ToString)

第一行将原始json字符串解析为JObject。这使我们能够以各种方式处理内容。例如,我们可以在json中引用对象,并按名称引用它们,这正是下一行所发生的情况:

The first line parses the original json string into a JObject. This allows us to work with the contents in various ways. For instance, we can reference "objects" in the json and them the items by name, which is exactly what happens in the next line:

' drill into "objects", get the "...hit2.ogg" item
Dim mi = js("objects")("minecraft/sounds/mob/blaze/hit2.ogg")

如果您只需要从大商店中获取特定物品,这将起作用文件。创建的 mi 变量是一个特殊 json令牌,因此请使用名称来获取所需的数据位

This will work if you just need to fetch a particular item from the big file. The mi variable created is a "special" json token, so use the names to get the data bits you want

hash = mi("hash").ToString
size = mi("size").ToString



方法2:反序列化为字典



这将是 my 首选方法。包含与第一个示例相同的 Import 语句,然后:

Method 2: Deserialize To a Dictionary

This would be my preferred method. Include the same Import statements as in the first example, then:

' parse the json string
Dim js As JObject = JObject.Parse(jstr)

' deserialize the inner "objects" to a NET Dictionary
Dim myItems = JsonConvert.DeserializeObject(Of Dictionary(Of String, _
                   MinecraftItem))(js("objects").ToString)

这将创建 myItems 作为网络 Dictionary(Of String,MincraftItem)来自json。由于 MinecraftObject 类不执行任何操作,而是保留字典,因此我们跳过了它。

This will create myItems as a Net Dictionary(Of String, MincraftItem) from the json. Since the MinecraftObject class doesn't do anything but hold the dictionary, we skipped it.

键是长名称,每个值都是 MinecraftItem ,可让您更常规地引用它们:

The keys are the long names and each value is a MinecraftItem which allows you to reference them more conventionally:

' get one of the items into a variable
gravel3 = myItems("minecraft/sounds/mob/chicken/step2.ogg")
ConsoleWriteLine("Gravel3  hash: {0},  size: {1}",
                      gravel3.hash, gravel3.size.ToString)

如果您不熟悉。Net字典它有点像数组或列表,只不过您可以通过 Key 而不是索引。要遍历它们:

If you are not familiar with the .Net Dictionary it is somewhat like an array or List except you access your items by a Key rather then index. To loop thru them all:

Dim n As Integer = 0
For Each kvp As KeyValuePair(Of String, MinecraftItem) In myItems
    Console.WriteLine("Name: {0}  Hash: {1}  size: {2}",
                      kvp.Key, 
                      kvp.Value.hash, 
                      kvp.Value.size.ToString)
    n += 1
    If n >= 2 Then Exit For           ' just print 3
Next                              

输出:


名称: realms / lang / de_DE.lang哈希:10a54fc66c8f479bb65c8d39c3b62265ac82e742大小:8112

名称:realms / lang / cy_GB.lang哈希:14cfb2f24e7d91dbc22a2a0e3b880b98bs / mob / b名称:7347 chicken / step2.ogg哈希:bf7fadaf64945f6b31c803d086ac6a652aabef9b大小:3838

Name: realms/lang/de_DE.lang Hash: 10a54fc66c8f479bb65c8d39c3b62265ac82e742 size: 8112
Name: realms/lang/cy_GB.lang Hash: 14cfb2f24e7d91dbc22a2a0e3b880d9829320243 size: 7347
Name: minecraft/sounds/mob/chicken/step2.ogg Hash: bf7fadaf64945f6b31c803d086ac6a652aabef9b size: 3838

请记住,密钥始终是长路径名,每个 .Value i s MinecraftItem 对象。

Just remember, the Key will always be the long path name, and each .Value is MinecraftItem object.

您可以使用 MinecraftContainer 类跳过解析步骤:

You can skip the parsing step by using the MinecraftContainer class:

Dim jstr As String = ...from whereever
Dim myJItems = JsonConvert.DeserializeObject(Of MinecraftContainer)(jstr)

请注意,这一次,您将下载的整个字符串 传递给 JsonConvert 。结果将是一个额外的外部对象,其中包含一个名为 Objects的字典属性。因此,您可以使用一些主要引用来引用这些项目:

Note that this time, you pass the entire string you downloaded to JsonConvert. The result will be an extra outer object which contains a dictionary property named "Objects". So, you reference the items using some leading references:

gravel3hash = myJItems.Object("minecraft/sounds/dig/gravel3.ogg").hash

gravel3 = myJItems.Object("minecraft/sounds/dig/gravel3.ogg")
    ConsoleWriteLine("Gravel3  hash: {0},  size: {1}",
                      gravel3.hash, gravel3.size.ToString)
'or:
ConsoleWriteLine("Gravel3  hash: {0},  size: {1}",
                   myJItems.Object("minecraft/sounds/dig/gravel3.ogg").hash, 
                   myJItems.Object("minecraft/sounds/dig/gravel3.ogg").size.ToString)   

此方法只是要反序列化的一行代码,但这意味着

a)我必须定义容器类,并且

b)我必须使用 myJItems.Object 钻入否则为空的容器,以获取Dictionary。

This method is just one line of code to deserialize, but it means
a) I have to define the container class and
b) I have to use myJItems.Object to drill into the otherwise empty container to get at the Dictionary.

我个人会放弃此方法,而使用方法2-额外的一行代码使其使用起来更加容易。也就是说,您还可以从容器中提取字典集合:

Personally, I would forego this and use method 2 - one extra line of code makes it a bit easier to work with. That said, you can also extract the dictionary collection from the container:

Dim myItems As Dictionary(Of String, MinecraftItem)= myJItems.Object

这篇关于反序列化Minecraft json的更好方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆