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
Related
I need to deserialize this weird JSON (image below). I've seen some deserialization hints using Dictionary<>, etc. but the problem is that "parameters" contains different data, then previous keys.
Can I somehow get it to work using JsonSerializer deserializator without doing foreach loops and other suspicious implementations? I do need data from "data" in my application.
Here's some of my code:
using var client = new WebClient();
var json = client.DownloadString(GetJsonString());
var invoicesData = JsonSerializer.Deserialize<JsonMyData>(json, options);
If using Newtonsoft is necessary I might start using it.
With Newtonsoft you can parse and access arbitrary JSON documents, even ones that can't reasonably be deserialized into a .NET object. So something like:
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using System;
namespace ConsoleApp35
{
class Program
{
static void Main(string[] args)
{
var json = #"
{
""myData"" :
{
""0"" : { ""data"": { ""A"":1,""B"":2} },
""1"" : { ""data"": { ""A"":1,""B"":2} },
""2"" : { ""data"": { ""A"":1,""B"":2} },
""3"" : { ""data"": { ""A"":1,""B"":2} },
""parameters"" : { ""p"":""a""}
},
""status"":{ }
}";
var foo = JObject.Parse(json);
var a = foo["myData"]["1"]["data"];
Console.WriteLine(a);
Console.WriteLine("Hit any key to continue");
Console.ReadKey();
}
}
}
I think you should really consider using Newtonsoft.Json instead of default JsonDeserializer, it is much easier to use in such situations.
If you are interested in processing this without foreach loops and wanting to access the data in a list format, I would suggest using Dictionary for this. When you use dictionary, you can use Objects as values that would compensate for differences in numbers (0, 1, 2, ..) and words (parameters).
// Classes to Deserialize data we need.
public class MyObject
{
[JsonProperty("data")]
public Data Data { get; set; }
}
public class Data
{
public int A { get; set; }
public int B { get; set; }
}
Usage in Main
// Read in the JSON
var myData = JsonConvert.DeserializeObject<dynamic>(jsonString)["myData"];
// Convert To Dictionary
Dictionary<string, dynamic> dataAsObjects = myData.ToObject<Dictionary<string, dynamic>>();
string searchFor = "3";
dataAsObjects.TryGetValue(searchFor, out dynamic obj);
if (obj != null)
{
// Conversion to int and matching against searchFor is to ensure its a number.
int.TryParse(searchFor, out int result);
if (result == 0 && result.ToString().Equals(searchFor))
{
MyObject myObject = obj.ToObject<MyObject>();
Console.WriteLine($"A:{myObject.Data.A} - B:{myObject.Data.B}");
}
else if (result == 8 && result.ToString().Equals(searchFor))
{
// I am not clear on whats your parameters class look like.
MyParameters myParams = obj.ToObject<MyParameters>();
}
}
Output
A:1 - B:2
With this method you can either access the numbers or the parameters element.
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 doing C# JSON <-> PHP JSON for the first time.
Thought I'd get on an easy road but seems like I've hit the rock.
I'm fairly sure that JSON from Newtonsoft allows "[" character but not sure why i have this error instead?
Here's my C# code:
public class SystemJSON
{
public bool Status { get; set; }
public string Message { get; set; }
public string ResponseData { get; set; }
}
public static class SystemCall
{
public static String Post(string uri, NameValueCollection pairs)
{
byte[] response = null;
using (WebClient wc = new WebClient())
{
response = wc.UploadValues(uri, pairs);
}
return Encoding.Default.GetString(response);
}
}
string system_Response = SystemCall.Post("http://127.0.0.1:8080/edsa-NEFS%20(PHP)/api.php", new NameValueCollection()
{
{"do_work", Functions.Get_Department_List.ToString()},
{"api_data", null }
});
**SystemJSON systemJSON = JsonConvert.DeserializeObject<SystemJSON>(system_Response);** //<-- Error happens here.
if(systemJSON.Status == true)
{
//do stuff here
}else
{
MessageBox.Show(this, systemJSON.Message, this.Text, MessageBoxButtons.OK, MessageBoxIcon.Warning);
}
And here's my PHP code:
<?php
// Load Request
$function_name = isset($_POST['do_work']) ? $_POST['do_work'] : '';
$api_data = isset($_POST['api_data']) ? $_POST['api_data'] : '';
// Validate Request
if (empty($function_name))
{
SystemResponse(false, 'Invalid Request');
}
if (!function_exists($function_name))
{
SystemResponse(false, 'API Method Not Implemented');
}
// Call API Method
call_user_func($function_name, $api_data);
/* Helper Function */
function SystemResponse($responseStatus, $responseMessage, $responseData = '')
{
exit(json_encode(array(
'Status' => $responseStatus,
'Message' => $responseMessage,
'ResponseData' => $responseData
)));
}
/* API Methods */
function Get_Department_List($api_data)
{
//Test ------------------------------------------START
$node = array();
$dept = array();
$responseData = array();
$dept['id'] = 1;
$dept['name'] = "General";
$dept['description'] = "Forms, Samples, Templates, Catalogs, etc";
$dept['status'] = 1;
array_push($node, $dept);
$dept['id'] = 2;
$dept['name'] = "Test";
$dept['description'] = "Testing";
$dept['status'] = 1;
array_push($node, $dept);
$responseData["dept"] = $dept;
SystemResponse(true, 'SUCCESS', $responseData);
//Test ------------------------------------------END
}
?>
And here's my error:
Newtonsoft.Json.JsonReaderException HResult=0x80131500
Message=Unexpected character encountered while parsing value: {. Path
'ResponseData', line 1, position 51.
The problem is that your C# SystemJSON class does not match the structure of the incoming JSON correctly.
ResponseData in your C# SystemJSON class is listed as a string but your PHP appears to be pushing out a complex object inside that property. You can't deserialise an object into a string - there is no way for the deserialiser to know how to translate the object structure into a suitable string, and anyway it's not generally a useful or logical thing to do. So instead it throws an error to say the object structure doesn't match.
The specific error you're seeing means the deserialiser is expecting a " to denote the start of a string but instead it's seeing { denoting the start of another object.
Why is this happening? Well, your PHP code will produce a JSON response which looks like this:
{
"Status": true,
"Message": "SUCCESS",
"ResponseData": {
"dept": {
"id": 2,
"name": "Test",
"description": "Testing",
"status": 1
}
}
}
Live demo here
As you can see, ResponseData contains an object, which has a "dept" which in turn is another object with four more properties.
To deserialise this properly, your SystemJSON class will need to be altered, and you'll also need two sub-classes to help it out:
public class SystemJSON
{
public bool Status { get; set; }
public string Message { get; set; }
public ResponseData ResponseData { get; set; }
}
public class ResponseData {
public Department dept {get; set; }
}
public class Department {
public string id {get; set; }
public string description {get; set; }
public int status {get; set; }
}
You will now be able to deserialise the JSON correctly. Here is a live demo of the deserialisation.
P.S the [ character appears to be irrelevant here...it's unclear why you referred to that in your question.
P.P.S. From looking at your PHP I'm guessing that you may be intending to return different data structures in ResponseData depending on which parameter was specified for do_work - i.e. depending on which PHP function is called. If so then you'll need to amend your C# accordingly so that it deserialises to a different concrete class depending on which API method it requests. Or you could possibly cheat and specify ResponseData as dynamic, which will then accept any data structure it received, albeit with the caveat that it's now effectively loosely-typed and so you lose certain benefits when compiling the code such as checking for valid usage of property names, data types etc.
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
I need to use some JSON data with a C# application, but i can't figure a way of getting the data.
I'm using SOCKET.IO, and here is a sample of a raw json string that is recieved
`socket.On("recieved", (data) =>
{
MessageBox.Show(data.Json.ToJsonString());
//outputs : {'name':'received','args':[{'data':'somedata'}]}
//get values from data
}`<br>
and i need to retrieve the value of 'data'
Look at the examples in the SocketIO4Net archive.
Define a class
using Newtonsoft.Json;
namespace TestProject
{
[JsonObject(MemberSerialization.OptIn)]
public class JSonData
{
[JsonProperty]
public string data { get; set; }
public JSonData()
{
}
public string ToJsonString()
{
return JsonConvert.SerializeObject(this);
}
public static JSonData Deserialize(string jsonString)
{
return JsonConvert.DeserializeObject<JSonData>(jsonString);
}
}
}
And after you get data like this :
JSonData JData = data.Json.GetFirstArgAs<JSonData>();
Ok i got that working, but if i want all args in JSON string {data:"somedata",anotherdata:'someanotherdata'} and get 'anotherdata', i tried `
JSonData part = data.Json.GetArgsAs();
Sorry for the double answers, but this did it for me
private Newtonsoft.Json.Linq.JObject get_data(SocketIOClient.Messages.JsonEncodedEventMessage data)
{
var inputdata = data;
dynamic jsondata = inputdata.GetArgsAs<Object>();
jsondata = jsondata[0];
return jsondata;
}
and then just do
dynamic json = get_data(data.Json);