Deserializing JSON using JSon.NET with dynamic data - json

I'm trying to deserialize some JSON data into objects for an application. Up until now it's been fine because the properties on the JSON data was static (key with a value). Now I've got a result where the key is a dynamic piece of data.
Here's an example JSON url:
http://en.wikipedia.org/w/api.php?action=query&format=json&pageids=6695&prop=info
The resulting JSON for this is:
{ "query" : { "pages" : { "6695" : { "counter" : "",
"lastrevid" : 468683764,
"length" : 8899,
"ns" : 0,
"pageid" : 6695,
"title" : "Citadel",
"touched" : "2012-01-03T19:16:16Z"
} } } }
Okay, that's great except I can't deserialize the "pages" data into an object. If I were to define a class for the pages it would have to look like this:
public class 6695
{
public string counter { get; set; }
public int lastrevid { get; set; }
public int length { get; set; }
public int ns { get; set; }
public int pageid { get; set; }
public string title { get; set; }
public string touched { get; set; }
}
In order to deserialze the contents (using JsonConvert.Deserialize(jsondata)) and we all know we can't have a class called 6695. Not only that, the name of the class would have to be different (for example pageid=7145 would have to be the 7145 class).
I can seem to pluck some values out if I use something like JObject.Parse(content) and then access items as JArrays but it's pretty ugly and I'm still stuck on trying to get out the data from the pages array.
Looking for someone to help with this. I don't think it's uncommon, it's just not JSON data I've come across before and not sure how to handle it.
Thanks!
PS forgot to mention this is on Windows Phone 7 so "dynamic" isn't available!

The simplest method. In this particular case would probably be to go dynamic.
dynamic data = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(json);
var lastRevId = data.query.pages["6695"].lastrevid;
You can reference any element by it's [] name so you can do something like data["query"]["pages"]["6695"]["lastrevid"]. This will get by all those little objects where the name isn't valid in c#.

Here is how you do using https://github.com/facebook-csharp-sdk/simple-json ( https://nuget.org/packages/SimpleJson ).
var text = "{\"query\":{\"pages\":{\"6695\":{\"pageid\":6695,\"ns\":0,\"title\":\"Citadel\",\"touched\":\"2012-01-03T19:16:16Z\",\"lastrevid\":468683764,\"counter\":\"\",\"length\":8899}}}}";
(Using dynamic)
dynamic json = SimpleJson.DeserializeObject(text);
string title = json.query.pages["6695"].title;
foreach (KeyValuePair<string, dynamic> page in json.query.pages)
{
var id = page.Key;
var pageId = page.Value.pageid;
var ns = page.Value.ns;
}
(Using strongly typed classes)
class result
{
public query query { get; set; }
}
class query
{
public IDictionary<string, page> pages { get; set; }
}
class page
{
public long pageid { get; set; }
public string title { get; set; }
}
var result = SimpleJson.DeserializeObject<result>(text);
[Update]
on windows phone where dynamic is not supported and you don't want to use strongly typed classes.
var json = (IDictionary<string, object>)SimpleJson.DeserializeObject(text);
var query = (IDictionary<string, object>)json["query"];
var pages = (IDictionary<string, object>)query["pages"];
var pageKeys = pages.Keys;
var page = (IDictionary<string, object>)pages["6695"];
var title = (string)page["title"];

I hope the below example will help.
I always design a model that match the json. It is much better to work with the object when it is your own model design.
It is very easy to generate the c# model from the json. I use this website to generate the model: http://json2csharp.com
A complete example is:
C# Code:
var targetsObject = Newtonsoft.Json.JsonConvert.DeserializeObject<YourModel>(jsonString);
JSON:
{
"investors": [
{
"name": "06",
"programs": [
{
"name": "Conventional",
"value": "3.5"
},
{
"name": "FHA - Standard",
"value": "5.0"
},
{
"name": "FHA - Streamline",
"value": ""
},
{
"name": "VA",
"value": "5.5"
},
{
"name": "VA IRRRL",
"value": "6.0"
},
{
"name": "Non-Prime",
"value": ""
}
]
},
{
"name": "07",
"programs": [
{
"name": "Conventional",
"value": "3.5"
},
{
"name": "FHA - Standard",
"value": "5.0"
},
{
"name": "FHA - Streamline",
"value": "7.0"
},
{
"name": "VA",
"value": "5.5"
},
{
"name": "VA IRRRL",
"value": ""
},
{
"name": "Non-Prime",
"value": ""
}
]
},
{
"name": "08",
"programs": [
{
"name": "Conventional",
"value": "3.5"
},
{
"name": "FHA - Standard",
"value": "5.0"
},
{
"name": "FHA - Streamline",
"value": "7.0"
},
{
"name": "VA",
"value": "5.5"
},
{
"name": "VA IRRRL",
"value": ""
},
{
"name": "Non-Prime",
"value": ""
}
]
},
{
"name": "09",
"programs": [
{
"name": "Conventional",
"value": "3.5"
},
{
"name": "FHA - Standard",
"value": "5.0"
},
{
"name": "FHA - Streamline",
"value": ""
},
{
"name": "VA",
"value": "5.5"
},
{
"name": "VA IRRRL",
"value": ""
},
{
"name": "Non-Prime",
"value": ""
}
]
},
{
"name": "10",
"programs": [
{
"name": "Conventional",
"value": ""
},
{
"name": "FHA - Standard",
"value": ""
},
{
"name": "FHA - Streamline",
"value": ""
},
{
"name": "VA",
"value": ""
},
{
"name": "VA IRRRL",
"value": ""
},
{
"name": "Non-Prime",
"value": "2.0"
}
]
},
{
"name": "11",
"programs": [
{
"name": "Conventional",
"value": "3.5"
},
{
"name": "FHA - Standard",
"value": "5.0"
},
{
"name": "FHA - Streamline",
"value": ""
},
{
"name": "VA",
"value": "6.0"
},
{
"name": "VA IRRRL",
"value": "6.0"
},
{
"name": "Non-Prime",
"value": ""
}
]
},
{
"name": "12",
"programs": [
{
"name": "Conventional",
"value": "3.5"
},
{
"name": "FHA - Standard",
"value": "5.0"
},
{
"name": "FHA - Streamline",
"value": ""
},
{
"name": "VA",
"value": "5.5"
},
{
"name": "VA IRRRL",
"value": "6.0"
},
{
"name": "Non-Prime",
"value": ""
}
]
},
{
"name": "13",
"programs": [
{
"name": "Conventional",
"value": ""
},
{
"name": "FHA - Standard",
"value": "5.0"
},
{
"name": "FHA - Streamline",
"value": ""
},
{
"name": "VA",
"value": ""
},
{
"name": "VA IRRRL",
"value": ""
},
{
"name": "Non-Prime",
"value": "2.0"
}
]
}
]
}
Model:
public class Program
{
public string name { get; set; }
public string value { get; set; }
}
public class Investor
{
public string name { get; set; }
public List<Program> programs { get; set; }
}
public class RootObject
{
public List<Investor> investors { get; set; }
}

Using Json.net you can just do:
Dictionary<string,object> result = JsonConvert.DeserializeObject<Dictionary<string,object>>(json);
foreach(var item in result)
Console.WriteLine(item.Key + " " + item.Value);

How about a simple search and replace in the JSON string ? While it might not be the most elegant solution, it would possibly be the most pragmatic one.

Maybe you could just use one reserved attribute to contain the object type, and then use the base type as shown in this article: Dynamic types with JSON.NET

Related

how to parse dynamic complex json to dart object or model

{
"transactionId": "11f8ecc05273e35a4eb2dc1a",
"type": "REQUEST_FOR_HH_INTERVIEW",
"answers": {
"selectProvinceDistrictCommuneVillage": {
"value": "01020706"
},
"positionOfOfficial": {
"value": "Province Officer"
},
"enterKhmerName": {
"value": "សុខ"
},
"selectSex": {
"value": "MALE"
},
"dob": {
"value": "1994-06-15T03:27:47.409Z"
},
"areYouMarried": {
"value": "YES"
},
"scanSpousesID": {
"value": "435465"
},
"enterSpousesKhmerName": {
"value": "នារី"
},
"selectSexSpouse": {
"value": "FEMALE"
},
"dobSpouse": {
"value": "1996-08-15T03:27:47.409"
},
"numberOfMales": {
"value": "4"
},
"numberOfFemales": {
"value": "5"
},
"selectReasonForRequesting": {
"value": [
"NATURAL_DISASTER"
]
}
}
}
So this is the JSON I need to parse into the dart model. The problem I am having with this structure is that map inside answers are all dynamic. Also, the number of the maps inside answers is not always the same. For example, the next JSON response can be.
{
"transactionId": "11f8ecc05273e35a4eb2dc1a",
"type": "REQUEST_FOR_HH_INTERVIEW",
"answers": {
"selectCode": {
"value": "01020706"
},
"selectRoomValue": {
"value": "1996-08-15T03:27:47.409"
},
"numberOfFamilyMembers": {
"value": "4"
},
"selectFoods": {
"value": [
"Piza",
"Burger"
]
}
}
}
which is different from the first response. I need to make a dart model that parses both responses.
This is relatively easy to do by using a "sub-model" of Answers which would be stored within the assumed InterviewRequest model.
For example:
class InterviewRequest {
final Answers answers;
final String transactionId;
factory InterviewRequest.fromJson(Map<String, dynamic> json) {
return InterviewRequest(
answers: Answers.fromJson(json['answers']),
transactionId: json['transactionId'] as String,
);
}
}
class Answers {
final List<Answer> answers;
factory Answers.fromJson(Map<String, dynamic> json) {
List answers = [];
for (String question in json.keys)
answers.add(Answer(question, json[key]));
return Answers(answers);
}
}

Transform and flatten JSON using GSON

I’m working on splitting a SignalK JSON object into canonical JSON items representing each value.
The original JSON looks like this:
{
"mmsi": "urn:mrn:signalk:uuid:5377770-4ee4-4a4b-3230-888037332031",
"name": "Mona",
"navigation": {
"position": {
"timestamp": "1991-09-03T03:5:36.000Z",
"latitude": 51.763691,
"longitude": 9.501367,
"altitude": 0.000000,
"source": "N0183-01"
},
"courseOverGroundTrue": {
"value": 23.000000
},
"speedOverGround": {
"value": 2.010289
}
},
"environment": {
"depth": {
"belowTransducer": {
"value": 12.700000
}
},
"wind": {
"angleApparent": {
"value": 0.174533
},
"speedApparent": {
"value": 0.000000
}
}}}
The needed transformed JSON looks like this, with JSON elements representing each value, and with item naming representing the whole path of the value.
{
"items": [{
"columns": {
"assetId": "urn:mrn:signalk:uuid:5377770-4ee4-4a4b-3230-888037332031",
"description": "EnvironmentWindSpeedApparent",
"isStep": false,
"name": "EnvironmentWindSpeedApparent",
"timestamps": 1523962903470,
"type": "numerical",
"values": 0.0
},
"key": "20180417-130143470EnvironmentWindSpeedApparent5377770-4ee4-4a4b-3230-888037332031"
}, {
"columns": {
"assetId": "urn:mrn:signalk:uuid:5377770-4ee4-4a4b-3230-888037332031",
"description": "EnvironmentWindAngleApparent",
"isStep": false,
"name": "EnvironmentWindAngleApparent",
"timestamps": 1523962903470,
"type": "numerical",
"values": 0.174533
},
"key": "20180417-130143470EnvironmentWindAngleApparent5377770-4ee4-4a4b-3230-888037332031"
}, {
"columns": {
"assetId": "urn:mrn:signalk:uuid:5377770-4ee4-4a4b-3230-888037332031",
"description": "EnvironmentDepthBelowTransducer",
"isStep": false,
"name": "EnvironmentDepthBelowTransducer",
"timestamps": 1523962903470,
"type": "numerical",
"values": 12.7
},
"key": "20180417-130143470EnvironmentDepthBelowTransducer5377770-4ee4-4a4b-3230-888037332031"
}, {
"columns": {
"assetId": "urn:mrn:signalk:uuid:5377770-4ee4-4a4b-3230-888037332031",
"description": "NavigationPositionLongitude",
"isStep": false,
"name": "NavigationPositionLongitude",
"timestamps": 1523962903470,
"type": "numerical",
"values": 9.501367
},
"key": "20180417-130143470NavigationPositionLongitude5377770-4ee4-4a4b-3230-888037332031"
}, {
"columns": {
"assetId": "urn:mrn:signalk:uuid:5377770-4ee4-4a4b-3230-888037332031",
"description": "NavigationPositionLatitude",
"isStep": false,
"name": "NavigationPositionLatitude",
"timestamps": 1523962903470,
"type": "numerical",
"values": 51.763691
},
"key": "20180417-130143470NavigationPositionLatitude5377770-4ee4-4a4b-3230-888037332031"
}, {
"columns": {
"assetId": "urn:mrn:signalk:uuid:5377770-4ee4-4a4b-3230-888037332031",
"description": "NavigationCourseOverGroundTrue",
"isStep": false,
"name": "NavigationCourseOverGroundTrue",
"timestamps": 1523962903470,
"type": "numerical",
"values": 23.0
},
"key": "20180417-130143470NavigationCourseOverGroundTrue5377770-4ee4-4a4b-3230-888037332031"
}, {
"columns": {
"assetId": "urn:mrn:signalk:uuid:5377770-4ee4-4a4b-3230-888037332031",
"description": "NavigationSpeedOverGround",
"isStep": false,
"name": "NavigationSpeedOverGround",
"timestamps": 1523962903470,
"type": "numerical",
"values": 2.010289
},
"key": "20180417-130143470NavigationSpeedOverGround5377770-4ee4-4a4b-3230-888037332031"
}
]}
How to do this transformation in a flexible way that adopts to changing sub-nodes being available in the original JSON ?
I’m transforming it now in a simplistic way, but would like to know if it can be done using JsonReader , gson or other ways of iterating through the original JSON object.
I ended up defining the object structure representing the transformed json, and writing a custom serializer to do the transformation. It could be more efficient ways of doing it, but this approach seems to be working OK.
public class SignalKDeserializer implements JsonDeserializer<TargetObject> {
//written based on examples from http://www.javacreed.com/gson-deserialiser-example/
final TargetObject targetObject = new TargetObject ();
#Override
public TargetObject deserialize(final JsonElement json, final Type typeOfT, final JsonDeserializationContext context)
throws JsonParseException {
final JsonObject jsonObject = json.getAsJsonObject();
traverse (jsonObject,0,"", mmsi);
return targetObject;
}
private void traverse (JsonObject jsonObject, Integer level, String parentName, String mmsi) {
Set<String> keys = jsonObject.keySet();
Iterator<?> keysIterator = keys.iterator ();
while( keysIterator.hasNext ()) {
String key = (String) keysIterator.next ();
String signalName = parentName+upperCaseFirst (key); //setting signalName to complete path of value
if (jsonObject.get (key) instanceof JsonObject) {
traverse ((jsonObject.get (key)).getAsJsonObject (),level+1,upperCaseFirst (signalName),mmsi);
} else if (jsonObject.get (key) instanceof JsonElement) {
if (level>0) {
try {
final Double value = jsonObject.get(key).getAsDouble ();
calendar = Calendar.getInstance ();
Long timeStamp = calendar.getTimeInMillis ();
Item targetItem = new Item ();
targetItem.columns.setIsStep (false);
targetItem.columns.setAssetId (mmsi);
targetItem.columns.setTimestamps (calendar.getTimeInMillis ());
targetItem.columns.setType ("numerical");
targetItem.columns.setDescription (signalName);
targetItem.columns.setValues (value);
targetItem.columns.setName (signalName);
targetItem.setKey (signaldateformat.format (timeStamp) + mmsi);
targetObject.items.add (targetItem);
}
catch (NumberFormatException n) {
// Expected, the value is non numerical and will not be transformed
}
}
}
}
}}
I'm using the serializer from my main class like this:
final GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(TargetObject.class, new SignalKDeserializer ());
final Gson gson = gsonBuilder.create();
TargetObject targetObject = gson.fromJson (jsonSignalK,TargetObject.class);
String jsonOutString = gson.toJson (targetObject);
jsonOutString contains the transformed json I needed.

How to process sabre InstaFlight API JSON response

I connected to saber InstaFlight API and got a result in JSON. The output string is too long and I can get their values. But my way is taking lots of memory storage. I want a way that takes less memory storage and a dynamic way in VB.NET.
The code below is working fine with no error:
response2 = DirectCast(postReq.GetResponse(), HttpWebResponse)
reader2 = New StreamReader(response2.GetResponseStream())
postReq.ContentType = "application/json; charset=utf-8"
Dim ser1 As JObject = JObject.Parse(reader2.ReadToEnd())
I can get the values like this, with no error:
ElapseTime1 = ser1("PricedItineraries")(0)("AirItinerary")("OriginDestinationOptions")("OriginDestinationOption")(0)("ElapsedTime").Value(Of String)()
However, it gets to a point that you need hundreds of variables and this is not the right way.
An example of the output JSON:
{ "PricedItineraries": [ { "AirItinerary": { "OriginDestinationOptions": { "OriginDestinationOption": [ { "FlightSegment": [ { "DepartureAirport": { "LocationCode": "JFK" }, "ArrivalAirport": { "LocationCode": "LAS" }, "MarketingAirline": { "Code": "AS" }, "ArrivalTimeZone": { "GMTOffset": -7 }, "TPA_Extensions": { "eTicket": { "Ind": true } }, "StopQuantity": 0, "ElapsedTime": 344, "ResBookDesigCode": "R", "MarriageGrp": "O", "Equipment": { "AirEquipType": 320 }, "DepartureDateTime": "2017-07-07T09:30:00", "ArrivalDateTime": "2017-07-07T12:14:00", "FlightNumber": 1251, "OnTimePerformance": { "Percentage": 70 }, "OperatingAirline": { "CompanyShortName": "VIRGIN AMERICA", "FlightNumber": 251, "Code": "VX" }, "DepartureTimeZone": { "GMTOffset": -4 } }, { "DepartureAirport": { "LocationCode": "LAS" }, "ArrivalAirport": { "LocationCode": "LAX" }, "MarketingAirline": { "Code": "AS" }, "ArrivalTimeZone": { "GMTOffset": -7 }, "TPA_Extensions": { "eTicket": { "Ind": true } }, "StopQuantity": 0, "ElapsedTime": 85, "ResBookDesigCode": "R", "MarriageGrp": "O", "Equipment": { "AirEquipType": 320 }, "DepartureDateTime": "2017-07-07T14:45:00", "ArrivalDateTime": "2017-07-07T16:10:00", "FlightNumber": 1475, "OnTimePerformance": { "Percentage": 36 }, "OperatingAirline": { "CompanyShortName": "VIRGIN AMERICA", "FlightNumber": 475, "Code": "VX" }, "DepartureTimeZone": { "GMTOffset": -7 } } ], "ElapsedTime": 580 }, { "FlightSegment": [ { "DepartureAirport": { "LocationCode": "LAX" }, "ArrivalAirport": { "LocationCode": "LAS" }, "MarketingAirline": { "Code": "AS" }, "ArrivalTimeZone": { "GMTOffset": -7 }, "TPA_Extensions": { "eTicket": { "Ind": true } }, "StopQuantity": 0, "ElapsedTime": 71, "ResBookDesigCode": "R", "MarriageGrp": "O", "Equipment": { "AirEquipType": 320 }, "DepartureDateTime": "2017-07-08T17:00:00", "ArrivalDateTime": "2017-07-08T18:11:00", "FlightNumber": 1480, "OnTimePerformance": { "Percentage": 55 }, "OperatingAirline": { "CompanyShortName": "VIRGIN AMERICA", "FlightNumber": 480, "Code": "VX" }, "DepartureTimeZone": { "GMTOffset": -7 } }, { "DepartureAirport": { "LocationCode": "LAS" }, "ArrivalAirport": { "LocationCode": "JFK" }, "MarketingAirline": { "Code": "AS" }, "ArrivalTimeZone": { "GMTOffset": -4 }, "TPA_Extensions": { "eTicket": { "Ind": true } }, "StopQuantity": 0,
I think you need to create a model for this result. According to this JSON, you have to create a class model.
If you have this JSON:
{
"dailyDealId": "432",
"discountPercentage": "0",
"product": {
"productId": "10",
"brandId": "10",
"departmentId": "3",
"name": "Baby Girl Velour Tunic & Snowflake Legging Set",
"description": "The pretty set",
"url": "http://whatever.whatever.com/files/whatever.tif"
}
You need this model:
public class Product
{
public string productId { get; set; }
public string brandId { get; set; }
public string departmentId { get; set; }
public string name { get; set; }
public string description { get; set; }
public string url { get; set; }
}
public class Data
{
public string dailyDealId { get; set; }
public string discountPercentage { get; set; }
public Product product { get; set; }
}

Elasticsearch NEST 2.x Field Names

I am upgrading to NEST 2.3.0 and trying to rewrite all queries that were originally written for NEST 1.x.
I am using the Couchbase transport plugin that pushes data from Couchbase to Elasticsearch.
POCO
public class Park
{
public Park()
{
}
public bool IsPublic { get; set; }
}
Mapping is like this
"mappings": {
"park": {
"_source": {
"includes": [
"doc.*"
],
"excludes": [
"meta.*"
]
},
"properties": {
"meta": {
"properties": {
"rev": {
"type": "string"
},
"flags": {
"type": "long"
},
"expiration": {
"type": "long"
},
"id": {
"type": "string",
"index": "not_analyzed"
}
}
},
"doc": {
"properties": {
"isPublic": {
"type": "boolean"
}
}
}
}
}
}
Sample document in elasticsearch
{
"_index": "parkindex-local-01",
"_type": "park",
"_id": "park_GUID",
"_source": {
"meta": {
"expiration": 0,
"flags": 33554433,
"id": "park_GUID",
"rev": "1-1441a2c278100bc00000000002000001"
},
"doc": {
"isPublic": true,
"id": "park_GUID"
}
}
}
My query in NEST
var termQuery = Query<Park>.Term(p => p.IsPublic, true);
ISearchResponse<T> searchResponse = this.client.Search<T>(s => s.Index("parkindex-local-01")
.Take(size)
.Source(false)
.Query(q => termQuery));
This query goes to Elasticsearch as below
{
"size": 10,
"_source": {
"exclude": [
"*"
]
},
"query": {
"term": {
"isPublic": {
"value": "true"
}
}
}
}
It doesn't retrieve any data, it will work only if I prefix the field name with "doc." so query becomes as below
{
"size": 10,
"_source": {
"exclude": [
"*"
]
},
"query": {
"term": {
"doc.isPublic": {
"value": "true"
}
}
}
}
How do I write the query above in NEST so it can properly interpret the field names, I tried using Nested Query with Path set to "doc", but that gave an error saying field is not of a nested type.
Do I need to change my mapping?
This all used to work in Elasticsearch 1.x and NEST 1.x, I guess this has to do with breaking changes to field names constraints.
Fields can no longer be referenced by shortnames in Elasticsearch 2.0.
isPublic is a property of the doc field, which is mapped as an object type, so referencing by the full path to the property is the correct thing to do.
NEST 2.x has some ways to help with field inference, an example
public class Park
{
public Doc Doc { get; set;}
}
public class Doc
{
public bool IsPublic { get; set;}
}
var termQuery = Query<Park>.Term(p => p.Doc.IsPublic, true);
client.Search<Park>(s => s.Index("parkindex-local-01")
.Take(10)
.Source(false)
.Query(q => termQuery));
results in
{
"size": 10,
"_source": {
"exclude": [
"*"
]
},
"query": {
"term": {
"doc.isPublic": {
"value": true
}
}
}
}
You may also want to take a look at the automapping documentation.

How to parse JSON string and check if result contains the text, then ignore or allow it?

I'm working on a Minecraft launcher, I have a problem, because my launcher uses the original way, and for example, here is the JSON:
{
"id": "1.8.1",
"time": "2014-11-24T14:13:31+00:00",
"releaseTime": "2014-11-24T14:13:31+00:00",
"type": "release",
"minecraftArguments": "--username ${auth_player_name} --version ${version_name} --gameDir ${game_directory} --assetsDir ${assets_root} --assetIndex ${assets_index_name} --uuid ${auth_uuid} --accessToken ${auth_access_token} --userProperties ${user_properties} --userType ${user_type}",
"minimumLauncherVersion": 14,
"assets": "1.8",
"libraries": [
{
"name": "com.ibm.icu:icu4j-core-mojang:51.2"
},
{
"name": "net.sf.jopt-simple:jopt-simple:4.6"
},
{
"name": "com.paulscode:codecjorbis:20101023"
},
{
"name": "com.paulscode:codecwav:20101023"
},
{
"name": "com.paulscode:libraryjavasound:20101123"
},
{
"name": "com.paulscode:librarylwjglopenal:20100824"
},
{
"name": "com.paulscode:soundsystem:20120107"
},
{
"name": "io.netty:netty-all:4.0.23.Final"
},
{
"name": "com.google.guava:guava:17.0"
},
{
"name": "org.apache.commons:commons-lang3:3.3.2"
},
{
"name": "commons-io:commons-io:2.4"
},
{
"name": "commons-codec:commons-codec:1.9"
},
{
"name": "net.java.jinput:jinput:2.0.5"
},
{
"name": "net.java.jutils:jutils:1.0.0"
},
{
"name": "com.google.code.gson:gson:2.2.4"
},
{
"name": "com.mojang:authlib:1.5.17"
},
{
"name": "com.mojang:realms:1.7.5"
},
{
"name": "org.apache.commons:commons-compress:1.8.1"
},
{
"name": "org.apache.httpcomponents:httpclient:4.3.3"
},
{
"name": "commons-logging:commons-logging:1.1.3"
},
{
"name": "org.apache.httpcomponents:httpcore:4.3.2"
},
{
"name": "org.apache.logging.log4j:log4j-api:2.0-beta9"
},
{
"name": "org.apache.logging.log4j:log4j-core:2.0-beta9"
},
{
"name": "org.lwjgl.lwjgl:lwjgl:2.9.1",
"rules": [
{
"action": "allow"
},
{
"action": "disallow",
"os": {
"name": "osx"
}
}
]
},
{
"name": "org.lwjgl.lwjgl:lwjgl_util:2.9.1",
"rules": [
{
"action": "allow"
},
{
"action": "disallow",
"os": {
"name": "osx"
}
}
]
},
{
"name": "org.lwjgl.lwjgl:lwjgl-platform:2.9.1",
"natives": {
"linux": "natives-linux",
"windows": "natives-windows",
"osx": "natives-osx"
},
"extract": {
"exclude": [
"META-INF/"
]
},
"rules": [
{
"action": "allow"
},
{
"action": "disallow",
"os": {
"name": "osx"
}
}
]
},
{
"name": "net.java.jinput:jinput-platform:2.0.5",
"natives": {
"linux": "natives-linux",
"windows": "natives-windows",
"osx": "natives-osx"
},
"extract": {
"exclude": [
"META-INF/"
]
}
},
{
"name": "tv.twitch:twitch:6.5"
},
{
"name": "tv.twitch:twitch-platform:6.5",
"rules": [
{
"action": "allow"
},
{
"action": "disallow",
"os": {
"name": "linux"
}
}
],
"natives": {
"linux": "natives-linux",
"windows": "natives-windows-${arch}",
"osx": "natives-osx"
},
"extract": {
"exclude": [
"META-INF/"
]
}
},
{
"name": "tv.twitch:twitch-external-platform:4.5",
"rules": [
{
"action": "allow",
"os": {
"name": "windows"
}
}
],
"natives": {
"windows": "natives-windows-${arch}"
},
"extract": {
"exclude": [
"META-INF/"
]
}
}
],
"mainClass": "net.minecraft.client.main.Main"
}
So, in the "libraries" [, the game libraries listed with "name":, and below, the libraries contains the rules that apply to them, I want to know this rules with the library file name, and apply the actions with it, but I don't have any idea, I using this code, but this only redirect the libraries.
Here is my code:
Dim item As String = Version
Dim client As New WebClient()
Await client.DownloadFileTaskAsync(New Uri("https://s3.amazonaws.com/Minecraft.Download/versions/" + item + "/" + item + ".json"), Root + "\versions\" + item + "\" + item + ".json")
Dim JSONREADER As New StreamReader(Root + "\versions\" + item + "\" + item + ".json")
json = JSONREADER.ReadToEnd()
JSONREADER.Close()
Dim JSONResult As Object = JsonConvert.DeserializeObject(Of Object)(json)
MinecraftArgs = JSONResult("minecraftArguments")
AssetIndex = JSONResult("assets")
MainClass = JSONResult("mainClass")
For Each i In JSONResult("libraries").Children()
LibrariesList.Add(i.ToObject(Of MClibraries).name)
Next
For example:
{
"name": "org.lwjgl.lwjgl:lwjgl:2.9.1",
"rules": [
{
"action": "allow"
},
{
"action": "disallow",
"os": {
"name": "osx"
}
}
]
},
The "name" as the name of the file, the "rules" there is two action: allow, disallow, under the disallow, there is the "os":, this sets the action, because
"os": {
"name": "osx"
}
this only allows the file in Windows and Linux, but disallows the file in mac OS X, so I want to get and apply this actions.
I want to add these libraries:
"libraries": [
{
"name": "com.ibm.icu:icu4j-core-mojang:51.2"
},
{
"name": "net.sf.jopt-simple:jopt-simple:4.6"
},
{
"name": "com.paulscode:codecjorbis:20101023"
},
{
"name": "com.paulscode:codecwav:20101023"
},
{
"name": "com.paulscode:libraryjavasound:20101123"
},
{
"name": "com.paulscode:librarylwjglopenal:20100824"
},
{
"name": "com.paulscode:soundsystem:20120107"
},
{
"name": "io.netty:netty-all:4.0.23.Final"
},
{
"name": "com.google.guava:guava:17.0"
},
{
"name": "org.apache.commons:commons-lang3:3.3.2"
},
{
"name": "commons-io:commons-io:2.4"
},
{
"name": "commons-codec:commons-codec:1.9"
},
{
"name": "net.java.jinput:jinput:2.0.5"
},
{
"name": "net.java.jutils:jutils:1.0.0"
},
{
"name": "com.google.code.gson:gson:2.2.4"
},
{
"name": "com.mojang:authlib:1.5.17"
},
{
"name": "com.mojang:realms:1.7.5"
},
{
"name": "org.apache.commons:commons-compress:1.8.1"
},
{
"name": "org.apache.httpcomponents:httpclient:4.3.3"
},
{
"name": "commons-logging:commons-logging:1.1.3"
},
{
"name": "org.apache.httpcomponents:httpcore:4.3.2"
},
{
"name": "org.apache.logging.log4j:log4j-api:2.0-beta9"
},
{
"name": "org.apache.logging.log4j:log4j-core:2.0-beta9"
},
And add these libraries if the rules allow Windows operating system:
{
"name": "org.lwjgl.lwjgl:lwjgl:2.9.1",
"rules": [
{
"action": "allow"
},
{
"action": "disallow",
"os": {
"name": "osx"
}
}
]
},
{
"name": "org.lwjgl.lwjgl:lwjgl_util:2.9.1",
"rules": [
{
"action": "allow"
},
{
"action": "disallow",
"os": {
"name": "osx"
}
}
]
},
{
"name": "org.lwjgl.lwjgl:lwjgl-platform:2.9.1",
"natives": {
"linux": "natives-linux",
"windows": "natives-windows",
"osx": "natives-osx"
},
"extract": {
"exclude": [
"META-INF/"
]
},
"rules": [
{
"action": "allow"
},
{
"action": "disallow",
"os": {
"name": "osx"
}
}
]
},
{
"name": "net.java.jinput:jinput-platform:2.0.5",
"natives": {
"linux": "natives-linux",
"windows": "natives-windows",
"osx": "natives-osx"
},
"extract": {
"exclude": [
"META-INF/"
]
}
},
{
"name": "tv.twitch:twitch:6.5"
},
{
"name": "tv.twitch:twitch-platform:6.5",
"rules": [
{
"action": "allow"
},
{
"action": "disallow",
"os": {
"name": "linux"
}
}
],
"natives": {
"linux": "natives-linux",
"windows": "natives-windows-${arch}",
"osx": "natives-osx"
},
"extract": {
"exclude": [
"META-INF/"
]
}
},
{
"name": "tv.twitch:twitch-external-platform:4.5",
"rules": [
{
"action": "allow",
"os": {
"name": "windows"
}
}
],
"natives": {
"windows": "natives-windows-${arch}"
},
"extract": {
"exclude": [
"META-INF/"
]
}
}
],
If in the rules only disallow, and in the disallow only for example OS X, this means the Windows, and the Linux allowed.
First edit your MClibraries class so that it looks like this:
Public Class MClibraries
Public name As String
Public rules As JArray
End Class
So to do what you're asking I start off with a list and a dictionary:
Private ReadOnly _librariesList As New List(Of String)
Private ReadOnly _disallowed As New Dictionary(Of String, String)
NOTE: You already have _librariesList, but yours is named LibrariesList.
Next, to get the libraries, I did this:
Dim item As String = Version
Dim client = New WebClient() With {.Proxy = Nothing}
Dim json = Await client.DownloadStringTaskAsync(New Uri(String.Format("http://s3.amazonaws.com/Minecraft.Download/versions/{0}/{0}.json", item)))
Dim jsonResult As Object = JsonConvert.DeserializeObject(Of Object)(json)
For Each i In jsonResult("libraries")
Dim entry As MClibraries = i.ToObject(Of MClibraries)() ' Converts object to MClibrary
_librariesList.Add(entry.name) ' Add the name of each entry to the listbox
If Not IsNothing(entry.rules) AndAlso entry.rules.Count = 2 Then ' Check to make sure it isn't empty
_disallowed.Add(entry.rules(1)("os")("name")) ' Gets the os that is disallowed
End If
Next
NOTE: Just add what you already have to this
Now you can access all the disallowed os's with the new dictionary "_disallowed". The key is the os that is disallowed and the value is the package.
If you want to see if the os matches the user os you can write the following. Also you will need to add the reference to System.Management and import it as well
Private _currentOs as String
'The following should go under the loading of a form
Dim osname As String = (From x In New ManagementObjectSearcher("SELECT * FROM Win32_OperatingSystem").Get().OfType(Of ManagementObject)()
Select x.GetPropertyValue("Caption")).FirstOrDefault()
'The following should go where you retrieve the libraries
For Each i In jsonResult("libraries")
Dim entry As MClibraries = i.ToObject(Of MClibraries)() ' Converts object to MClibrary
If Not IsNothing(entry.rules) AndAlso entry.rules.Count = 2 Then ' Check to make sure it isn't empty
If Not _currentOs.ToLower.Contains(entry.rules(1)("os")("name")) Then
_librariesList.Add(entry.name)
End If
End If
Next