How can I deserialize a string in C# that only have values and no name. It looks like this: The problem is that this stream of string does not have name and uses array.
{
"result": {
"14400": [
[
1502985600,
262.18,
262.18,
257,
257,
1096.0131
],
[
1503000000,
257,
261.33,
254.8,
257,
1130.5897
]
],
"14405": [
[
1503014400,
258.03,
261.5,
257.01,
257.01,
520.7805
],
[
1503028800,
258,
260.98,
252.4,
259.56,
298.5658
],
]
]
}
}
Just create a class like
public class Root
{
public Dictionary<int,List<List<double>>> Result { get; set; }
}
and deserialize as
var res = JsonConvert.DeserializeObject<Root>(json);
I see it's an array, you could create a method to parse the class out of given JArray.
The Jason data
public void methpod()
{
string json ="Your jason value "
var factory = new Factory();
var suggest = factory.Create(json);
Console.WriteLine(suggest);
}
Make a class as suggested :
public class Factory
{
public Evan Create(string json)
{
var array = JArray.Parse(json);
string search = array[0].ToString();
string[] terms = array[1].ToArray().Select(item => item.ToString()).ToArray();
return new Evan{Search = search, Terms = terms};
}
}
and another
public class Evan
{
public string Search { get; set; }
public IEnumerable<string> Terms { get; set; }
public override string ToString()
{
return string.Format("Search={0},Terms=[{1}]",
Search, string.Join(",", Terms));
}
}
Tip
If you have JSON that you want to deserialize, and you don't have the class to deserialize it into, Visual Studio 2019 can automatically generate the class you need:
Copy the JSON that you need to deserialize.
Create a class file and delete the template code.
Choose Edit > Paste Special > Paste JSON as Classes.
The result is a class that you can use for your deserialization target
Related
I have a JSON file setup as such
{
"cards": [
{
"id": "sand_bags",
"type": "Structure",
"name": "Sand Bags",
"values": [
{
"civilian": 1,
"fiend": -1
}
],
"effectTexts": [
{
"civilian": "Add +1 to your BUNKER.",
"fiend": "Send any CIVILIAN'S +1 STRUCTURE to the SCRAPYARD."
}
],
"flavorTexts": [
{
"civilian": "They're just heavy bags with sand. Not much else to say, but they'll slow down an attack from a fiend. Good luck, you'll need it!",
"fiend": "You've spotted a pretty bad STRUCTURE in this BUNKER. Time to do some damage."
}
],
"staysOnField": [
{
"civilian": true,
"fiend": false
}
],
"amountInDeck": 5
}
]
}
I also have a Cards script
[Serializable]
public class Cards
{
public Card[] cards;
}
[Serializable]
public class Card
{
public string id;
public string type;
public string name;
public int amountInDeck;
}
public class Values
{
public int civilian;
public int fiend;
}
I then have a CardEffects script that I'm using for my functions.
public class CardEffects : MonoBehaviour
{
public TextAsset jsonFile;
public Values values;
void Start()
{
Cards cardsInJson = JsonUtility.FromJson<Cards>(jsonFile.text);
foreach (Card card in cardsInJson.cards)
{
Debug.Log("Card name: " + card.name + " with " + values.civilian + " in the deck.");
}
}
}
I have searched all over trying to figure out how to even get the array of objects of "values". I got this far and the value printed is always 0 regardless of the information in "values" in the JSON. If I make the class Serializable, I'm able to change the values and it works but I want the values to be whatever they were declared as in the JSON. Is there a better way to do this?
Please keep in mind I'm new to C# and Unity. I usually code in JS in which using JSON files are no big deal for me and thought it was the best way to go.
Your json and your classes doesn't match. Not only that your json isn't even valid Json. Below I will give you your correct json and class.
{
"cards": [
{
"id": "sand_bags",
"type": "Structure",
"name": "Sand Bags",
"values": [
{
"civilian": 1,
"fiend": -1
}
],
"effectTexts": [
{
"civilian": "Add +1 to your BUNKER.",
"fiend": "Send any CIVILIAN'S +1 STRUCTURE to the SCRAPYARD."
}
],
"flavorTexts": [
{
"civilian": "They're just heavy bags with sand. Not much else to say, but they'll slow down an attack from a fiend. Good luck, you'll need it!",
"fiend": "You've spotted a pretty bad STRUCTURE in this BUNKER. Time to do some damage."
}
],
"staysOnField": [
{
"civilian": true,
"fiend": false
}
],
"amountInDeck": 5
}
] // <---- This was missing
}
For that Json this is how your card class will have to look like:
public Card
{
public string id { get; set; }
public string type { get; set; }
public string name { get; set; }
public Values[] values { get; set; }
public Values[] effectTexts { get; set; }
public Values[] staysOnField { get; set; }
public int amountInDeck { get; set; }
}
And your Values class have to look like this:
public class Values
{
public object civilian;
public object fiend;
}
I suggest MiniJson.
You can just copy paste the script to your project and you are ready to go.
The then can call Json.Deserialize(string json) passing your string in. For the case of an array you can do for example:
IList myJsonElements = (IList)Json.Deserialize(string json);
Find working snippet:
using System;
using Newtonsoft.Json;
namespace ConsoleApp3
{
class Program
{
static void Main(string[] args) {
string myJson = "{\"cards\": [{\"id\": \"sand_bags\",\"type\": \"Structure\",\"name\": \"Sand Bags\",\"values\": [{\"civilian\": 1,\"fiend\": -1}],\"effectTexts\": [{\"civilian\": \"Add +1 to your BUNKER.\",\"fiend\": \"Send any CIVILIAN'S +1 STRUCTURE to the SCRAPYARD.\"}],\"flavorTexts\": [{\"civilian\": \"They're just heavy bags with sand. Not much else to say, but they'll slow down an attack from a fiend. Good luck, you'll need it!\",\"fiend\":\"You've spotted a pretty bad STRUCTURE in this BUNKER. Time to do some damage.\"}],\"staysOnField\": [{\"civilian\": true,\"fiend\": false}],\"amountInDeck\": 5}]}";
var myJsonElements = MiniJSON.Json.Deserialize(myJson);
Console.WriteLine(myJsonElements.ToString());
string json = JsonConvert.SerializeObject(myJsonElements, Formatting.Indented);
Console.WriteLine(json);
Console.ReadLine();
}
}
}
I am pretty new to JSON and C# and have created an Azure Function that ties back to Snowflake which requires a very specific type of JSON response. I would like assistance if any in turning a JSON response I'm getting to a slightly different formatted response.
{
"access_token": "access token value here" , "user": "user_val"
}
to looking like
{
"data":
[
[ 0, { "access_token" : "access token value here", "user" : "user_val" } ]
]
}
I need create a nested array with "data" as the parent and a row number response starting at 0.
Using Json.NET:
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
public class Program
{
public static void Main()
{
string json = #"{
""access_token"": ""access token value here"" , ""user"": ""user_val""
}";
Access a = JsonConvert.DeserializeObject<Access>(json);
var accessCollection = new AccessCollection
{
Data = new List<Access> { a }
};
json = JsonConvert.SerializeObject(accessCollection, Formatting.Indented);
Console.WriteLine(json);
}
}
public class Access
{
[JsonProperty("access_token")]
public string AccessToken
{
get;
set;
}
[JsonProperty("user")]
public string User
{
get;
set;
}
}
public class AccessCollection
{
[JsonProperty("data")]
public List<Access> Data
{
get;
set;
}
}
In addition, I consider the inner array is not usual because the data type are int and object. In general, they should be of same type. Because of that, I use a single dimensional array instead.
Please modify the codes according to situation.
.NET Fiddle
Let's say I have this example JSON:
"Test": {
"KIf42N7OJIke57Dj6dkh": {
"name": "test 1"
},
"xsQMe4WWMu19qdULspve": {
"name": "test 2"
}
}
I want to parse this into an Array of a custom class I have, which will be exampled below:
class Class1 {
public string Name { get; set; }
Class1(string name) {
Name = name;
}
}
How can I parse this using Json.NET's JObject.Parse?
You can achieve your goal with JPath query like this :
var myArray = JObject
.Parse(json)
.SelectTokens("$.Test..name")
.Values<string>()
.Select(s => new Class1(s))
.ToArray();
But probably not the best way to do it.
I personnaly prefere to create classes to represent the json structure and then apply transformations.
void Main()
{
var json = #"{""Test"": {
""KIf42N7OJIke57Dj6dkh"": {
""name"": ""test 1""
},
""xsQMe4WWMu19qdULspve"": {
""name"": ""test 2""
}
}
}";
var root = JsonConvert.DeserializeObject<Root>(json);
var array = root.Test.Select(i => i.Value).ToArray();
array.Dump();
}
public class Root
{
public Dictionary<string, Class1> Test { get; set; }
}
public class Class1
{
public string Name { get; set; }
public Class1(string name)
{
Name = name;
}
}
To begin with, your Json is missing starting/closing braces. The Json needs to have wrapping braces around the Test value.
{
'Test':
{
'KIf42N7OJIke57Dj6dkh': {'name': 'test 1'},
'xsQMe4WWMu19qdULspve': {'name': 'test 2'}
}
}
If you are missing it in the original Json, you could wrap the current input Json as following.
var correctedJson = $"{{{inputJsonString}}}";
If you want to parse the Json Objects to Array of Class1 without creating additional concrete data structures and using JPath Queries, you could use Anonymous Types for the purpose using the DeserializeAnonymousType Method proved by Json.Net. For example,
var sampleObject = new {Test = new Dictionary<string,Class1>()};
var data = JsonConvert.DeserializeAnonymousType(correctedJson,sampleObject);
var result = data.Test.Select(x=>x.Value).ToArray();
You could also achieve it using JPath Query or creating Concrete Data Structures as #Kalten as described in his answer.
I'm trying to handle deresealize an object that does not comply with some of my classes. I wold like the code to execute and fail only on the invalid attributes but the deserealization method is returning a null Object.
I am using this method in a generic utility class that deserealizes some string to any given type.
From the test code, the error handler works correctly on invalid dates and other invalid types and returns the object with the default .NET initialization values.
If I change (or comment) the Items collection in the sub object, the code works.
string json = "{\"Id\":8,\"CreatedByUserId\":0,\"CreatedOnDate\":\"2019X-Y02Z-W06T18:A51:05.783\",\"LastModifiedByUserId\":1,\"LastModifiedOnDate\":\"2019-03-12T17:00:34.82\",\"OperationData\":{\"IsActive\":true,\"Items\":[{\"_Id\":1,\"Id_Value\":0,\"Id\":1},{\"_Id\":2,\"Id\":2},{\"Id\":1,\"IsDeleted\":false,\"Content\":{}}]}}";
TestType test = DeserealizeContent(json);
/*The convertion utility*/
private static TestType DeserealizeContent(string data)
{
var settings = new JsonSerializerSettings
{
NullValueHandling = NullValueHandling.Ignore,
MissingMemberHandling = MissingMemberHandling.Ignore,
Error = HandleDeserializationError
};
var r = JsonConvert.DeserializeObject<TestType>(data, settings);
return r;
}
public static void HandleDeserializationError(object sender, ErrorEventArgs errorArgs)
{
errorArgs.ErrorContext.Handled = true;
}
/*Supporting types*/
public class TestType {
public int Id { get; set; }
public DateTime CreatedOnDate { get; set; }
public int CreatedByUserId { get; set; }
public string Instructions { get; set; }
public OperationDataType OperationData {get;set;}
}
public class OperationDataType {
public bool IsActive { get; set; }
public List<int> Items { get; set; }
}
I was expecting the error handler to catch handle the exception and continue with the process but instead the deserealization just returns null in the end.
If I change List Items to List Items the result is correctly parsed.
My expected result wold be:
{
"Id": 8,
"CreatedByUserId": 0,
"CreatedOnDate": null,
"LastModifiedByUserId": 1,
"LastModifiedOnDate": "2019-03-12T17:00:34.82",
"OperationData": {
"IsActive": true,
"Items": null
}
}
EDIT - workaround
The suggestion from Yair (bellow) works.
Changing from List to List works as expected and the exception get handle correctly.
The items in your json is not an array of int so how you want it to be List?
Items is array of objects look at the json formated:
{
"Id": 8,
"CreatedByUserId": 0,
"CreatedOnDate": "2019X-Y02Z-W06T18:A51:05.783",
"LastModifiedByUserId": 1,
"LastModifiedOnDate": "2019-03-12T17:00:34.82",
"OperationData": {
"IsActive": true,
"Items": [{
"_Id": 1,
"Id_Value": 0,
"Id": 1
}, {
"_Id": 2,
"Id": 2
}, {
"Id": 1,
"IsDeleted": false,
"Content": {}
}
]
}
}
You can do one of three things:
handle the json content as string or map it so the items will be int array [1,2,3].
create item class for the items that include all the fields you need then extract the int that you want.
get it as object like you do now and use reflection () for getting the int you want.
you can use this function for reflection:
public static object GetPropValue(object src, string propName)
{
return src.GetType().GetProperty(propName).GetValue(src, null);
}
and then use it like this:
GetPropValue(test.OperationData.items[0], "Id")
EDIT
you can use this to deserialize the json in generic way:
Newtonsoft.Json.Linq.JObject jsonDeserialized = (Newtonsoft.Json.Linq.JObject)Newtonsoft.Json.JsonConvert.DeserializeObject<object>(json);
and then
you can map it manually or with automapper to the new TestType test that you want without the items in it.
you can get the values like this:
test.Id = jsonDeserialized["Id"];
test.CreatedByUserId = jsonDeserialized["CreatedByUserId"];
and so on
according to your last comment i find that if i changed the List<int> Items to List<long> Items it works as you wanted. it is something with primitive types and the parsing that deserialize do.
I am building a server dashboard app. I want to take a list of disks from each server and create a list that displays the usage values for each.
Here's a JSON sample we're getting back...
{"server":"webster","disks":[ {"use": "91%", "used": "16G", "mount": "/", "free": "1.6G", "device": "/dev/mapper/vg_f12-lv_root", "total": "18G", "type": "ext4"} ,
{"use": "0%", "used": "0", "mount": "/dev/shm", "free": "500M", "device": "tmpfs", "total": "500M", "type": "tmpfs"} ,
{"use": "22%", "used": "40M", "mount": "/boot", "free": "145M", "device": "/dev/sda1", "total": "194M", "type": "ext4"} ,
{"use": "47%", "used": "52G", "mount": "/rsync", "free": "61G", "device": "/dev/sdb1", "total": "119G", "type": "ext3"} ]}
I get this far with the C# code:
WebClient c = new WebClient();
var data = c.DownloadString("http://192.0.0.40:8000/cgi-bin/df.py");
JObject o = JObject.Parse(data);
string serv = o["server"].Select(s => (string)s).ToString();
lblJson.Text = serv;
But I can't seem to extract "disks" into anything meaningful that I can plugin to a listview. I've tried pumping this into IList, but it always crashes or gives me some rude comments from Intellisense.
I do have a class built for this, but haven't figured out how to port the info into it. For reference, it's here:
public class drive
{
public string Usage;
public string usedSpace;
public string Mount;
public string freeSpace;
public string Device;
public string Total;
public string Type;
}
Note: The sources for JSON are Linux servers. Windows servers will supply data in a different format ultimately.
And then we have VMWare, but I'll flail on that later.
Thanks in advance.
var jsonObj = JsonConvert.DeserializeObject<RootObject>(json);
public class RootObject
{
[JsonProperty("server")]
public string Server;
[JsonProperty("disks")]
public List<Drive> Disks;
}
public class Drive
{
[JsonProperty("use")]
public string Usage;
[JsonProperty("used")]
public string usedSpace;
[JsonProperty("mount")]
public string Mount;
[JsonProperty("free")]
public string freeSpace;
[JsonProperty("device")]
public string Device;
[JsonProperty("total")]
public string Total;
[JsonProperty("type")]
public string Type;
}
There may be a better way to do this, but using the provided drive class, the following works to deserialize your provided JSON:
JObject o = JObject.Parse(data);
List<drive> drives = new List<drive>();
string server = (string)o["server"];
foreach (var d in o["disks"].Children())
{
drives.Add(new drive()
{
Usage = (string)d["use"],
usedSpace = (string)d["used"],
Mount = (string)d["mount"],
freeSpace = (string)d["free"],
Device = (string)d["device"],
Total = (string)d["total"],
Type = (string)d["type"]
});
}