I created a file which named by a given name by user, and add some stats in it for example : healt, power, speed, inventory like so. Now, i want to create a function that get stats from given path. It need find the file from given name and get the stat.
I tried re-read the file as note/json so on and it didnt work very well. I want to get variables like :
if(inventory.Contains("Bread"))
Note : I tried to save files as .json but it saved as unknown note i dont know how and why.
...
...
CharacterData Character = new CharacterData()
{
health = 100,
power = 100,
speed = 100,
dexterity = 100,
hungry = 100,
weapon = "Fist",
inventory = new List<string>()
{
"Bread"
}
};
string stringjson = JsonConvert.SerializeObject(Character);
File.WriteAllText(characterPath, stringjson);
}
public int GetCharInfo(string charName,string stat)
{
//return (stat value)
}
you can do something like this:
CharacterData Character = new CharacterData()
{
health = 100,
power = 100,
speed = 100,
dexterity = 100,
hungry = 100,
weapon = "Fist",
inventory = new List<string>()
{
"Bread"
}
};
string stringjson = JsonConvert.SerializeObject(Character);
string path = #"C:\DEV\StackOverflow\";
string characterPath = path + "johnny.json";
File.WriteAllText(characterPath, stringjson);
public int GetCharInfo(string charName, string stat)
{
string json = File.ReadAllText(path + $"{charName}.json");
JObject obj = JObject.Parse(json);
return (int)obj[stat];
}
now if you call:
GetCharInfo("johnny", "power")
you will get the value:
100
also, if you want to see if the key exists you can use the ContainsKey method on JObject like such:
if(obj.ContainsKey(stat))
return (int)obj[stat];
UPDATE
if you want to get a "stat" of different type I suggest doing this:
have this method that gets the character as a json object
public JObject GetCharacterJSON(string charName){
string json = File.ReadAllText(path + $"{charName}.json");
return JObject.Parse(json);
}
now you can load this inside a variable
JObject johnny = GetCharacterJSON("johnny);
And you can get the inventory property like such:
List<string> inventory = johnny["inventory"].ToObject<List<string>>();
As a suggestion, from my point of view if I were you I would try to deserialize the json string into a CharacterData object and then use that like this:
public CharacterData GetCharacterData(string charName){
string json = File.ReadAllText(path + $"{charName}.json");
return JsonConvert.DeserializeObject<CharacterData>(json);
}
CharacterData characterData = GetCharacterData("johnny");
int power = characterData.power; //100
List<string> inventory = characterData.inventory; //["Bread"]
if(inventory.Contains("Bread"){
//do something
}
Note: I didn't take into account error handling in all examples for when the file does not exist or property does not exist etc. I've just outlined the general principle in order to be simple to understand.
Thanks
I guess begin with
File.ReadAllText(path)
Example of usage and documentation
https://learn.microsoft.com/en-us/dotnet/api/system.io.file.readalltext?view=net-6.0
Then you can covert the result to JSON and extract the information that you want
Related
I'm making a Scoreboard for a game. I'm developing but have no experience with json.
So far I have made it so it adds a name with a score into a plain text file and also displaying this in game.
Now I want to sort it so that the name with the lowest score goes to the top.
Here is my code:
[WebMethod]
public static void Score(String gamescore, string loginname)
{
List<Highscore> Myhighscores = new List<Highscore>();
string hs = File.ReadAllText(#"c:\temp\hs.txt");
Myhighscores = JsonConvert.DeserializeObject<List<Highscore>>(hs);
Myhighscores.Add(new Highscore { Score = gamescore, Name = loginname });
string Jstr = JsonConvert.SerializeObject(Myhighscores);
File.WriteAllText(#"c:\temp\hs.txt", Jstr);
}
public void displayScore()
{
using (StreamReader r = new StreamReader(#"c:\temp\hs.txt"))
{
string json = r.ReadToEnd();
List<Highscore> items = JsonConvert.DeserializeObject<List<Highscore>>(json);
foreach (Highscore score in items)
{
lblHighscore.Text += $"{score.Name} > {score.Score} {"Turns"}<br/>";
}
}
}
I have tried a lot of things but nothing seems to be working.
Does anyone know how I can achieve this?
p.s Highscore contains 2 public strings called Name and Score.
You need to sort your object before writing it again back in file.
Myhighscores.Sort((x, y) => string.Compare(x.Score, y.Score));
Its pretty easy all i needed to do is change gamescore to a int and add the following code:
List<Highscore> SortedList = items.OrderBy(o => o.Score).ToList();
I have a simple class to define rooms. Initially I set up all the rooms I need, (Could be hundreds in a long list), though in my example I set up just 3. Then I have a string that I will use to reference the right instance of Rooms class. For instance, this could be "X10Y10". I want to use that string to identify the corresponding Rooms instance, but don't know how to associate them.
void Start () {
Rooms X10Y10 = new Rooms();
X10Y10.Name = "The Great Room";
X10Y10.RoomMonsters = 10;
X10Y10.Ref = "001";
Rooms X11Y10 = new Rooms();
X11Y10.Name = "Smoking room";
X11Y10.RoomMonsters = 2;
X11Y10.Ref = "002";
Rooms X12Y10 = new Rooms();
X12Y10.Name = "Hunting Room";
X12Y10.RoomMonsters = 7;
X12Y10.Ref = "003";
// Don't Know the room Ref until runtime, during game.
// Want to get the room instance properties of one of the rooms eg.
string RoomAtRuntime = "X11Y10"; // dont know this until game is running
// fix following lines
print(RoomAtRuntime.RoomMonster); // would return 2
print(RoomAtRuntime.Name); // would return Smoking room
}
public class Rooms
{
public string Ref { get; set; }
public string Name { get; set; }
public int RoomMonsters { get; set; }
}
It sounds like what you need here is a Dictionary - a collection which associates Keys with Values. In your case, you can associate each string key with a different Rooms instance, making it easy (and efficient) to quickly access any instance. Here's what your code might look like with this change:
// Declare and initialize dictionary before using it
private Dictionary<string, Rooms> roomCollection = new Dictionary<string, Rooms>();
void Start () {
// After you instantiate each room, add it to the dictionary with the corresponding key
Rooms X10Y10 = new Rooms();
X10Y10.Name = "The Great Room";
X10Y10.RoomMonsters = 10;
X10Y10.Ref = "001";
roomCollection.Add("X10Y10", X10Y10);
Rooms X11Y10 = new Rooms();
X11Y10.Name = "Smoking room";
X11Y10.RoomMonsters = 2;
X11Y10.Ref = "002";
roomCollection.Add("X11Y10", X11Y10);
Rooms X12Y10 = new Rooms();
X12Y10.Name = "Hunting Room";
X12Y10.RoomMonsters = 7;
X12Y10.Ref = "003";
roomCollection.Add("X12Y10", X12Y10);
// The rooms should now all be stored in the dictionary as key-value pairs
string RoomAtRuntime = "X11Y10";
// Now we can access any room by its given string key
print(roomCollection[RoomAtRuntime].RoomMonster);
print(roomCollection[RoomAtRuntime].Name);
}
Note that you may need to add the directive using System.Collections.Generic to your script file.
You can (and probably should) also use something other than a string for your key value. Here, I think it'd make more sense to use a Vector2 value for these X/Y coordinates, rather than strings. (So, something like roomCollection.Add(new Vector2(10, 10), X10Y10); would be more appropriate.)
Hope this helps! Let me know if you have any questions.
I'm trying to loop over a JSON string in my Android app. This is the code I have so far, using answers I found on line.
private void updateAutoComplete() {
var testJSON = "{result:[{\"symbol\":\"FB\",\"typeDisp\":\"Equity\",\"exchDisp\":\"NASDAQ\",\"exch\":\"NAS\",\"name\":\"Facebook, Inc.\",\"type\":\"S\"},{\"symbol\":\"FB2A.DE\",\"typeDisp\":\"Equity\",\"exchDisp\":\"XETRA\",\"exch\":\"GER\",\"name\":\"Facebook, Inc.\",\"type\":\"S\"}]}";
var autoCompleteOptions = getAutoCompleteOptions (testJSON);
ArrayAdapter autoCompleteAdapter = new ArrayAdapter(this, Android.Resource.Layout.SimpleDropDownItem1Line, autoCompleteOptions);
var autocompleteTextView = FindViewById<AutoCompleteTextView>(Resource.Id.AutoCompleteInput);
autocompleteTextView.Adapter = autoCompleteAdapter;
}
private String[] getAutoCompleteOptions(String json) {
var autoCompleteOptions = new String[20];
int i = 0;
dynamic dynObj = JsonConvert.DeserializeObject(json);
foreach (var data in dynObj.result) { //x
autoCompleteOptions.SetValue (data.symbol, i);
i++;
}
return autoCompleteOptions;
}
Want I want is to get the different symbols from the JSON in an array so I can use it for the autocomplete.
When I run the app (updateAutoComplete is called in the OnCreate), I get following error: 'Newtonsoft.Json.Linq.JObject' does not contain a definition for 'result' on the line marked with the x.
Anyone know what might be the problem?
Thanks in advance.
If you are trying to go the route of not serializing back into an object you can cherry pick the data out of the string that you need with a JObject.
JObject root = JObject.Parse(testJSON);
var result = (JArray)root["result"];
result.ToList().ForEach(x =>
{
var symbol = x["symbol"];
symbol.Dump();
});
//FB
//FB2A.DE
I receive a string in this format:
{
"ok": true,
"quote": { // the below is the same as returned through the REST quote API
"symbol": "FAC",
"venue": "OGEX",
"bid": 5100, // best price currently bid for the stock
"ask": 5125, // best price currently offered for the stock
"bidSize": 392, // aggregate size of all orders at the best bid
"askSize": 711, // aggregate size of all orders at the best ask
"bidDepth": 2748, // aggregate size of *all bids*
"askDepth": 2237, // aggregate size of *all asks*
"last": 5125, // price of last trade
"lastSize": 52, // quantity of last trade
"lastTrade": "2015-07-13T05:38:17.33640392Z", // timestamp of last trade,
"quoteTime": "2015-07-13T05:38:17.33640392Z" // server ts of quote generation
}
}
I want to use the Newtonsoft.Json.Linq way of deserializing for performance reasons. When I try to turn the Json string into a Quote object using the following method:
public static Quote QuoteFromJson(string quoteJson)
{
var json = JObject.Parse(quoteJson);
var quote = json["quote"].
Select(q => new Quote
{
Ask = int.Parse(q["ask"].ToString()),
AskDepth = int.Parse(q["askDepth"].ToString()),
AskSize = int.Parse(q["askSize"].ToString()),
Bid = int.Parse(q["bid"].ToString()),
BidDepth = int.Parse(q["bidDepth"].ToString()),
BidSize = int.Parse(q["bidSize"].ToString()),
Last = int.Parse(q["last"].ToString()),
LastSize = int.Parse(q["lastSize"].ToString()),
LastTrade = q["lastTrade"].ToString(),
QuoteTime = q["quoteTime"].ToString(),
Symbol = q["symbol"].ToString(),
}).First();
return quote;
}
This gives an error message:
Cannot access child value on Newtonsoft.Json.Linq.JProperty
What am I doing wrong?
Here is a direct answer to your question:
The quote variable corresponds to the quote token in your JSON. This is a single item and not a collection, so you shouldn't treat it as a collection and use the Select method.
Instead, access it directly like this:
var json = JObject.Parse(quoteJson);
var quote = json["quote"];
var result = new Quote
{
Ask = int.Parse(quote["ask"].ToString()),
AskDepth = int.Parse(quote["askDepth"].ToString()),
AskSize = int.Parse(quote["askSize"].ToString()),
Bid = int.Parse(quote["bid"].ToString()),
BidDepth = int.Parse(quote["bidDepth"].ToString()),
BidSize = int.Parse(quote["bidSize"].ToString()),
Last = int.Parse(quote["last"].ToString()),
LastSize = int.Parse(quote["lastSize"].ToString()),
LastTrade = quote["lastTrade"].ToString(),
QuoteTime = quote["quoteTime"].ToString(),
Symbol = quote["symbol"].ToString(),
};
Your problem is that you are iterating through the children of "quote" with your Select, then retrieving their properties by name. This would be appropriate if "quote" were an array, but it's not -- it's already a single object. Thus you should do:
var rootObj = JObject.Parse(quoteJson);
var quoteObj = rootObj["quote"];
var quote = new Quote
{
Ask = (int)quoteObj["ask"],
AskDepth = (int)quoteObj["askDepth"],
AskSize = (int)quoteObj["askSize"],
Bid = (int)quoteObj["bid"],
BidDepth = (int)quoteObj["bidDepth"],
BidSize = (int)quoteObj["bidSize"],
Last = (int)quoteObj["last"],
LastSize = (int)quoteObj["lastSize"],
LastTrade = (string)quoteObj["lastTrade"],
QuoteTime = (string)quoteObj["quoteTime"],
Symbol = (string)quoteObj["symbol"],
};
Note I am using explicit casting. This handles internationalization of numbers in a manner consistent with the JSON standard. int.Parse() parses using localized formatting, which is not guaranteed to be consistent with the standard in all locales.
However, it is much simpler to use deserialization:
var rootObj = JObject.Parse(quoteJson);
var quoteObj = rootObj["quote"];
var quote = quoteObj.ToObject<Quote>();
I suggest you should time this to make sure it really is slower than Linq to JSON.
I have my list as below,
var serie_line = new { name = series_name , data =new List<float?>() };
In the above code data in another list which contains float value, I want data to contains two different datatype value that is string and float value, when I am trying to add two different datatype values as follow,
var serie_line = new { name = series_name , data =new List<string, float?>() };
It gives me an error as
Using the generic type'System.Collections.Generic.List<T>' requires 1 argument.
I cannot try for data=new List<Tupple<string,float>>();..since I am using .NET 3.5...any idea..hw cn I deal with this problem..thank you,
----------Updated question---------
Output that I requires is as follows,
{
"legend":{"enabled":"true"},
"title":{"text":"Financial"},
"chart":{"type":"pie"},
"series":
[
{"name":"Actual-","data":[["Market Share",20.00],["Sales Growth",30.00],["Operating Profit",40.00],["Actual-Gross Margin %",10.00]]}
]
},
this data list should contains one string value and one float value...I want to draw pie chart in highcharts but output I am getting is as follows,
{
"legend":{"enabled":"true"},
"title":{"text":"Financial"},
"chart":{"type":"column"},
"series":[{"name":"Actual","data":[{"Str":"Market Share","Flo":20.00}]},
{"name":"Actual","data":[{"Str":"Sales Growth","Flo":30.00}]},
{"name":"Actual","data":[{"Str":"Operating Profit","Flo":40.00}]},
{"name":"Actual","data":[{"Str":"Gross Margin %","Flo":10.00}]}
]
}
Any Idea...???
----------Use of Dictionary----------
var data = new Dictionary<string, float?>();
var serie_line = new { name = series_name, data };
serie_line.data.Add(child_object_name, period_final_value);
but this doesnot give required output...
it only gives values inside data as for eg,
"data":["market share":20.00].. since I am serializing serie_line into JSON...but I don't want this way..what I want is "data":["market share",20.00]
I hope u get this...
just use
new Dictionary<string, float?>() //if your string value cannot be duplicated
//or
new List<KeyValuePair<string,float?> >
create a type to be use with your list:
public class MyDataType
{
public string Str {get; set;}
public float? Flo {get;set;}
}
you use it like this:
var serie_line = new { name = series_name , data =new List<MyDataType>() };
serie_line.data.Add(new MyDataType{Flo = 45.4});
or like:
var serie_line = new { name = series_name , data =new List<MyDataType>() };
serie_line.data.Add(new MyDataType{Flo = 45.4, Str = "my string"});
If you are trying to add items to a list so that both are available you need to use List<object>(), as its the only shared type between both. That or use ArrayList.
As you pull the objects out you will need to test if they are objects of type string or float? in order to cast them back. You may be able to wrap them.
Use ArrayList, the non-generic version of List.
How about something more structured:
public struct MyData
{
public float? FloatData;
public string StringData;
}
var serie_line = new
{
name = series_name,
data = new MyData()
{
FloatData = theFloatData,
StringData = theStringData,
}
};