0

I'm currently trying to create a small launcher to solve some problems using the existing launcher from minecraft. I'm trying to read a .json file to get all the informations that i need. If you need to take a look at the .json file here.

I got it working if i just need a single information like

string clienturl = readJson("//downloads/client/url");

with this:

private string readJson(string element)
{
    string json = File.ReadAllText(Path.Combine(appPath + "1.10.2.json"));
    var jsonReader = JsonReaderWriterFactory.CreateJsonReader(Encoding.UTF8.GetBytes(json), new System.Xml.XmlDictionaryReaderQuotas());

    var root = XElement.Load(jsonReader);

    return root.XPathSelectElement(element).Value;
}

The problem now is that i need to get informations for all the other files. The "element" would be:

libraries/downloads/artifact/path
libraries/downloads/artifact/url

but obviously there is more then one entry for "path" and "url" so i need a foreach loop. What do i need to change in my code above to make it working with a foreach loop?

Sorry for my bad english, i hope its not to hard to understand.

Small preview of the .json in case you dont want to download the file:

"libraries": [
{
    "name": "com.mojang:netty:1.6",
    "downloads": {
        "artifact": {
            "size": 7877,
            "sha1": "4b75825a06139752bd800d9e29c5fd55b8b1b1e4",
            "path": "com/mojang/netty/1.6/netty-1.6.jar",
            "url": "https://libraries.minecraft.net/com/mojang/netty/1.6/netty-1.6.jar"
        }
    }
},
{
    "name": "oshi-project:oshi-core:1.1",
    "downloads": {
        "artifact": {
            "size": 30973,
            "sha1": "9ddf7b048a8d701be231c0f4f95fd986198fd2d8",
            "path": "oshi-project/oshi-core/1.1/oshi-core-1.1.jar",
            "url": "https://libraries.minecraft.net/oshi-project/oshi-core/1.1/oshi-core-1.1.jar"
        }
    }
},
{
    "name": "net.java.dev.jna:jna:3.4.0",
    "downloads": {
        "artifact": {
            "size": 1008730,
            "sha1": "803ff252fedbd395baffd43b37341dc4a150a554",
            "path": "net/java/dev/jna/jna/3.4.0/jna-3.4.0.jar",
            "url": "https://libraries.minecraft.net/net/java/dev/jna/jna/3.4.0/jna-3.4.0.jar"
        }
    }
}
]
Backslash
  • 99
  • 1
  • 10
  • Why do you not want to use a json library? You will be finished in 2 minutes using them – Sir Rufo Jun 26 '16 at 21:38
  • @SirRufo there are many ways to work with .json files in .net, the one i'm using above is only one. I just dont realy see a "need" to use third party libraries to get what i want. i'm sure there are also many ways to loop through .json without third party libraries, i'm currently just dont know how. – Backslash Jun 26 '16 at 22:24
  • Sure there are a lot of ways and you can build a house with a kids shovel. I recommend to use the right tools for the job to get the work done. With Json.NET you will be finished in 2 minutes. Just my 2 cents – Sir Rufo Jun 26 '16 at 22:43

1 Answers1

0

The issue is that your JSON contains an array, and it's not immediately obvious how JsonReaderWriterFactory maps an array to XML elements, given that XML doesn't have the concept of an array.

One way to determine this is to read through the documentation Mapping Between JSON and XML which describes this mapping. But another is simply to determine for ourselves, by using one of the answers from Get the XPath to an XElement? to find out the actual paths for each element. Using this answer, the following code:

var paths = root.DescendantsAndSelf().Select(e => e.GetAbsoluteXPath()).ToList();
Debug.WriteLine(String.Join("\n", paths));

Produces output like:

/root/libraries
/root/libraries/item[1]
/root/libraries/item[1]/name
/root/libraries/item[1]/downloads
/root/libraries/item[1]/downloads/artifact
/root/libraries/item[1]/downloads/artifact/size
/root/libraries/item[1]/downloads/artifact/sha1
/root/libraries/item[1]/downloads/artifact/path
/root/libraries/item[1]/downloads/artifact/url
/root/libraries/item[2]
/root/libraries/item[2]/name
/root/libraries/item[2]/downloads
/root/libraries/item[2]/downloads/artifact
/root/libraries/item[2]/downloads/artifact/size
/root/libraries/item[2]/downloads/artifact/sha1
/root/libraries/item[2]/downloads/artifact/path
/root/libraries/item[2]/downloads/artifact/url

So, as you can see, each array item is placed in a synthetic <item> node.

Thus you can query your paths and urls as follows:

var files = root
    .XPathSelectElements("libraries/item/downloads/artifact")
    .Select(e => new PathAndUrl { Path = (string)e.Element("path"), Url = (string)e.Element("url") })
    .ToList();

Placing the result into a list of the following class:

public class PathAndUrl
{
    public string Path { get; set; }
    public string Url { get; set; }
}
dbc
  • 104,963
  • 20
  • 228
  • 340