I am new to converting json to csv. I have a complex json file. I am trying with following code to strongly derserialize to c# class. but nothing is working. firstly not able to deserialize and not sure the best way to write this to csv. there are around 20 entries in the json like "0", ..."19".
json data:
{
"0": [
{
"filenames": [
"a.txt",
"b.txt",
"c.txt"
]
},
{
"cluster_number": 0
},
{
"Top_Terms": [
"would",
"get",
"like"
]
}
],
"1": [
{
"filenames": [
"a.txt",
"b.txt",
"c.txt"
]
},
{
"cluster_number": 0
},
{
"Top_Terms": [
"would",
"get",
"like"
]
}
]
}
c# classes:
[DataContract(Name ="0")]
public class Zero
{
public IList<string> filenames { get; set; }
public int? cluster_number { get; set; }
public IList<string> Top_Terms { get; set; }
}
[DataContract(Name = "1")]
public class One
{
public IList<string> filenames { get; set; }
public int? cluster_number { get; set; }
public IList<string> Top_Terms { get; set; }
}
[DataContract]
public class Example
{
public IList<Zero> Zero { get; set; }
public IList<One> One { get; set; }
}
using (StreamReader r = new StreamReader("data.json"))
{
string json = r.ReadToEnd();
var result = JsonConvert.DeserializeObject<Example>(json);
}
Related
I have a JSON object with multiple classes and values as shown below:
{
"Class 1": [
{
"Key1": "value1",
"Key2": "value3"
},
{
"Key3": "value3",
"Key4": "value4"
}
],
"Class 2": [
{
"Key11": "value11",
"Key21": "value31"
},
{
"Key31": "value31",
"Key41": "value41"
}
],
"Class 3": [
{
"Key112": "value112",
"Key212": "value312"
},
{
"Key312": "value312",
"Key412": "value412"
}
],
"Class 4": [
{
"Key12": "value12",
"Key22": "value32"
},
{
"Key32": "value32",
"Key42": "value42"
},
{
"Key321": "value321",
"Key421": "value421"
}
]
}
I wanted to remove certain classes entirely and get the rest class in a JSON Object. i.e, I want to take only Class 2 and Class 4 from that Object. Could anyone help me achieve this? Thanks in advance. The expected output is shown below:
{
"Class 2" : [
{
"Key11": "value11",
"Key21": "value31"
},
{
"Key31": "value31"
"Key41": "value41"
}
],
"Class 4" : [
{
"Key12": "value12",
"Key22": "value32"
},
{
"Key32": "value32"
"Key42": "value42"
},
{
"Key321": "value321"
"Key421": "value421"
}
]
}
First, your JSON is invalid, there are some missing commas.
Your JSON should be as:
{
"Class 1" : [
{
"Key1": "value1",
"Key2": "value3"
},
{
"Key3": "value",
"Key4": "value4"
}
],
"Class 2" : [
{
"Key11": "value11",
"Key21": "value31"
},
{
"Key31": "value31",
"Key41": "value41"
}
],
"Class 3" : [
{
"Key112": "value112",
"Key212": "value312"
},
{
"Key312": "value312",
"Key412": "value412"
}
],
"Class 4" : [
{
"Key12": "value12",
"Key22": "value32"
},
{
"Key32": "value32",
"Key42": "value42"
},
{
"Key321": "value321",
"Key421": "value421"
}
]
}
And your JSON is an object, or also can be recognized as Dictionary<string, List<object>> type.
Concept:
Deserialize as Dictionary<string, List<object>> type.
Filter the x.Key by remainedKeys.
Cast the filtered result to the Dictionary/key-value pair.
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
List<string> remainedKeys = new List<string> { "Class 2", "Class 4" };
var result = JObject.Parse(json_string)
.ToObject<Dictionary<string, List<dynamic>>>()
.Where(x => remainedKeys.Contains(x.Key))
.ToDictionary(x => x.Key, x => x.Value);
Sample Program
try this
string[] classesNeeded = new string[] { "Class 2", "Class 4" };
var jsonParsed = JObject.Parse(json);
jsonParsed.Properties()
.Where(p => !classesNeeded.Contains(p.Name))
.ToList()
.ForEach(prop => prop.Remove());
json = jsonParsed.ToString();
Even as the #Yong Shun answer is the correct way to do it (mapping the Object)
You can take a roundabout and do a Deep clone serializing/deserializing (it could seem be a little hacky, but it works)
CompleteClass test;
//Fill your data
LimitedClass result = JsonConvert.DeserializeObject<LimitedClass>(JsonConvert.SerializeObject(test));
then you can serialize (again) result and obtain a JSON text to send to your file
Example classes definition:
public class Class1
{
public string Key1 { get; set; }
public string Key2 { get; set; }
public string Key3 { get; set; }
public string Key4 { get; set; }
}
public class Class2
{
public string Key11 { get; set; }
public string Key21 { get; set; }
public string Key31 { get; set; }
public string Key41 { get; set; }
}
public class Class3
{
public string Key112 { get; set; }
public string Key212 { get; set; }
public string Key312 { get; set; }
public string Key412 { get; set; }
}
public class Class4
{
public string Key12 { get; set; }
public string Key22 { get; set; }
public string Key32 { get; set; }
public string Key42 { get; set; }
public string Key321 { get; set; }
public string Key421 { get; set; }
}
public class CompleteClass
{
public List<Class1> Class1 { get; set; }
public List<Class2> Class2 { get; set; }
public List<Class3> Class3 { get; set; }
public List<Class4> Class4 { get; set; }
}
public class LimitedClass
{
public List<Class2> Class2 { get; set; }
public List<Class4> Class4 { get; set; }
}
I have little to no experience in JSON and I am stuck with a problem. Any help is appreciated.
I want to access specifically the names' values from the additionalInformation array.
JSON Response:
{
"statusCode": 200,
"version": 1,
"jsonData": [
{
"additionalInformation": [
{
"id": "XXX94XXXX9xxXx_xxxXXXX",
"name": "xxxx xxx x xxxxxxxx"
},
{
"id": "0xXXxcXxv5PQqT$6i2zLgV",
"name": "xxx xxxxxxxx"
},
{
"id": "11Krt_our2rPCPqJ_2fKZR",
"name": "xxx xxxxxxxx xx"
},
{
"id": "2jYw4IyBP8KuozM_ej7DGf",
"name": "xxxxxxx 1"
},
{
"id": "3B8O805wL1ufabHMz1Je3v",
"name": "xxxxxxx 2"
},
{
"id": "0FVKUYZkvFaxd_OQUiyPBZ",
"name": "xxxxxxx"
},
{
"id": "3O41QFd0573QQvFco5zUUP",
"name": "Xxxxxxxxx"
}
],
"type": 0
}
],
"errorMessages": [],
"warningMessages": [],
"informationMessages": []
}
Model:
public class CFunctions
{
public int statusCode { get; set; }
public int version { get; set; }
public List<PFunctions>[] jsonData { get; set; }
public List<string> errorMessages { get; set; }
public List<string> warningMessages { get; set; }
public List<string> informationMessages { get; set; }
/*public CFunctions()
{
jsonData = new List<PFunctions>();
}*/
}
[Serializable]
public class PFunctions
{
public List<PAdditionalInfo>[] additionalInformation { get; set; }
public int type { get; set; }
/*public PFunctions()
{
additionalInformation = new List<PAdditionalInfo>();
}*/
}
[Serializable]
public class PAdditionalInfo
{
public Guid id { get; set; }
public string name { get; set; }
}
Deserialisation
var request = UnityWebRequest.Get(baseurl);
var operation = request.SendWebRequest();
var jsonResponse = request.downloadHandler.text;
List<CFunctions>[] PFunctionsList = JsonConvert.DeserializeObject<List<CFunctions>[]>(jsonResponse);
Error:
Cannot deserialize the current JSON object into type 'System.Collections.Generic.List`1[CFunctions][]' because the type requires a JSON array to deserialize correctly.
To fix this error either change the JSON to a JSON array or change the deserialized type so that it is a normal .NET type that can be deserialized from a JSON object.
JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
Path 'statusCode', line 1, position 14.
UnityEngine.Debug:Log(Object)
What I tried
The error pertains even when I changed List<PAdditionalInfo> to List<PAdditionalInfo>[]
I am not sure how to use JsonObjectAttribute and if it is the best way.
You've declared an array of List<T> in the models, eg List<PAdditionalInfo>[]. The json represents single arrays, not nested. You can fix that by choosing one or the other (I decided to use List<> but array is valid too):
public class PFunctions
{
public List<PAdditionalInfo> additionalInformation { get; set; } // removed []
...
}
public class CFunctions
{
public int statusCode { get; set; }
public int version { get; set; }
public List<PFunctions> jsonData { get; set; } // removed []
...
}
The class you're deserializing to is incorrect. Deserialize to the correct type (which is CFunctions not List<CFunctions>[]):
CFunctions cFunctions = JsonConvert.DeserializeObject<CFunctions>(json);
the most efficient way to get an additional information is this one line code and you only need one class
List<AdditionalInformation> additionalInformation = JObject.Parse(json)
["jsonData"][0]["additionalInformation"].ToObject<List<AdditionalInformation>>();
class
public class AdditionalInformation
{
public string id { get; set; }
public string name { get; set; }
}
I have below JSON file,
[
{
"applicationConfig": {
"Name": "Name1",
"Site": "Site1"
},
"pathConfig": {
"SourcePath": "C:\\Temp\\Outgoing1",
"TargetPath": "C:\\Files"
},
"credentialConfig": {
"Username": "test1",
"password": "super1"
}
},
{
"applicationConfig": {
"Name": "Name2",
"Site": "Site2"
},
"pathConfig": {
"SourcePath": "C:\\Temp\\Outgoing2",
"TargetPath": "C:\\Files"
},
"credentialConfig": {
"Username": "test2",
"password": "super2"
}
}
]
And below are C# classes structure,
public class Configurations
{
public List<ApplicationConfig> ApplicationConfigs { get; set; }
public List<PathConfig> PathConfigs { get; set; }
public List<CredentialConfig> CredentialConfigs { get; set; }
}
public class ApplicationConfig
{
public string Name { get; set; }
public string Site { get; set; }
}
public class PathConfig
{
public string SourcePath { get; set; }
public string TargetPath { get; set; }
}
public class CredentialConfig
{
public string Username { get; set; }
public string password { get; set; }
}
Now trying to load JSON and getting below error,
using (var streamReader = new StreamReader(#"./Config.json"))
{
var X = JsonConvert.DeserializeObject<Configurations>(streamReader.ReadToEnd());
}
$exception {"Cannot deserialize the current JSON array (e.g. [1,2,3])
into type 'ConsoleApp8.Configurations' because the type requires a
JSON object (e.g. {\"name\":\"value\"}) to deserialize
correctly.\r\nTo fix this error either change the JSON to a JSON
object (e.g. {\"name\":\"value\"}) or change the deserialized type to
an array or a type that implements a collection interface (e.g.
ICollection, IList) like List that can be deserialized from a JSON
array. JsonArrayAttribute can also be added to the type to force it to
deserialize from a JSON array.\r\nPath '', line 1, position
1."} Newtonsoft.Json.JsonSerializationException
What else I need to serialize?
Your JSON represents an array - although the closing [ should be a ]. But you're trying to serialize it into a single Configurations object. Additionally, you seem to be expecting separate arrays for the application configs, path configs and credential configs - whereas your JSON shows an array of objects, each of which has all three.
I suspect you want:
public class Configuration
{
[JsonProperty("applicationConfig")]
ApplicationConfig ApplicationConfig { get; set; }
[JsonProperty("pathConfig")]
PathConfig PathConfig { get; set; }
[JsonProperty("credentialConfig")]
CredentialConfig CredentialConfig { get; set; }
}
// Other classes as before, although preferably with the password property more conventionally named
Then use:
List<Configuration> configurations =
JsonConvert.DeserializeObject<List<Configuration>>(streamReader.ReadToEnd());
You'll then have a list of configuration objects, each of which will have the three "subconfiguration" parts.
Your JSON class definition is close but not quite. Moroever the last [ must be ]
JSON class definition is created wtih QuickType
public partial class Configuration
{
[JsonProperty("applicationConfig")]
public ApplicationConfig ApplicationConfig { get; set; }
[JsonProperty("pathConfig")]
public PathConfig PathConfig { get; set; }
[JsonProperty("credentialConfig")]
public CredentialConfig CredentialConfig { get; set; }
}
public partial class ApplicationConfig
{
[JsonProperty("Name")]
public string Name { get; set; }
[JsonProperty("Site")]
public string Site { get; set; }
}
public partial class CredentialConfig
{
[JsonProperty("Username")]
public string Username { get; set; }
[JsonProperty("password")]
public string Password { get; set; }
}
public partial class PathConfig
{
[JsonProperty("SourcePath")]
public string SourcePath { get; set; }
[JsonProperty("TargetPath")]
public string TargetPath { get; set; }
}
Finally you need to serialize with
var config_list = JsonConvert.DeserializeObject<List<Configuration>>(streamReader.ReadToEnd());
I think it is a typo, you are opening the square bracket instead of closing it in the JSON file.
[ {
"applicationConfig": {
"Name": "Name1",
"Site": "Site1"
},
"pathConfig": {
"SourcePath": "C:\Temp\Outgoing1",
"TargetPath": "C:\Files"
},
"credentialConfig": {
"Username": "test1",
"password": "super1"
} }, {
"applicationConfig": {
"Name": "Name2",
"Site": "Site2"
},
"pathConfig": {
"SourcePath": "C:\Temp\Outgoing2",
"TargetPath": "C:\Files"
},
"credentialConfig": {
"Username": "test2",
"password": "super2"
} } [ <-HERE
I am using Xamarin forms and Newtonsoft to deserialize
It doesn't work:
var itens = JsonConvert.DeserializeObject<List<Model.Loja>>(json);
Here is my JSON:
{
"one": {
"two": [
{
"cod": 142,
"nome": "name",
"phone": "23423",
"endereco": "address",
"cidade": "city"
},
{
"cod": 142,
"nome": "name",
"phone": "23423",
"endereco": "address",
"cidade": "city"
}
]
}
}
Your model needs to match your JSON structure. Try using these classes:
public class RootObject
{
public One one { get; set; }
}
public class One
{
public List<Loja> two { get; set; }
}
public class Loja
{
public int cod { get; set; }
public string nome { get; set; }
public string phone { get; set; }
public string endereco { get; set; }
public string cidade { get; set; }
}
Then deserialize like this:
List<Loja> items = JsonConvert.DeserializeObject<RootObject>(json).one.two;
You can make a specific model class for that json, try to use http://json2csharp.com/,
and then you can parse it using newtonsoft.
If you are using json2chsarp then your specific class will called RootObject, but you can rename it to match your model.
var obj = JsonConvert.DeserializeObject<YourSpecificClass>(json);
The problem was the "[ ]".
I used
response = json.Substring(json.IndexOf('['));
response = json.Substring(0, json.LastIndexOf(']') + 1);
And solved it.
I have a complex JSON object that I'd like to pass to a MVC4 Controller route.
{
"name": "Test",
"description": "Description",
"questions": [
{
"id": "1",
"type": "1",
"text": "123",
"answers": [
{
"answer": "123",
"prerequisite": 0
},
{
"answer": "123",
"prerequisite": 0
}
],
"children": [
{
"id": "2",
"type": "2",
"text": "234",
"answers": [
{
"answer": "234",
"prerequisite": 0
},
{
"answer": "234",
"prerequisite": 0
}
],
"children": []
}
]
}
]
I have these ViewModels defined:
public class FormDataTransformContainer
{
public string name { get; set; }
public string description { get; set; }
public QuestionDataTransformContainer[] questions;
}
public class QuestionDataTransformContainer {
public int type { get; set; }
public string text { get; set; }
public AnswerDataTransformContainer[] answers { get; set; }
public QuestionDataTransformContainer[] children { get; set; }
}
public class AnswerDataTransformContainer {
public string answer { get; set; }
public int prerequisite { get; set; }
}
And this is the route I'm hitting:
[HttpPost]
public ActionResult Create(FormDataTransformContainer formData)
{
Currently, the name and description property on FormDataTransformContainer are set, but the questions array is null. I hoped that the Data Binding would figure it out, but I assume the tree nature of the data structure is a little complex for it. If I'm correct what is the best solution to this?
questions should be a property, not a field. I'd also change from arrays to IList<> (assuming your serialization library handles that well), because that's probably closer to what it should be, and lets you use a more generic interface instead of a specific implementation.
public class FormDataTransformContainer
{
public string name { get; set; }
public string description { get; set; }
public IList<QuestionDataTransformContainer> questions { get; set; }
}
public class QuestionDataTransformContainer {
public int type { get; set; }
public string text { get; set; }
public IList<AnswerDataTransformContainer> answers { get; set; }
public IList<QuestionDataTransformContainer> children { get; set; }
}
public class AnswerDataTransformContainer {
public string answer { get; set; }
public int prerequisite { get; set; }
}
I've tested this structure with Json.net (MVC4's default, I believe), and it works.
As #robert-harvey said, you should utilize libraries like JSON.NET that are already available to do the heavy lifting for you.
Pulled from the JSON.NET API docs:
If you create a string json that holds your json, you can read from it with new JsonTextReader(new StringReader(json))
I a similar problem, solved with the following code:
public class ExtendedController : Controller
{
public T TryCreateModelFromJson<T>(string requestFormKey)
{
if (!this.Request.Form.AllKeys.Contains(requestFormKey))
{
throw new ArgumentException("Request form doesn't contain provided key.");
}
return
JsonConvert.DeserializeObject<T>(
this.Request.Form[requestFormKey]);
}
}
And usage:
[HttpPost]
[ActionName("EditAjax")]
public ActionResult EditAjaxPOST()
{
try
{
var viewModel =
this.TryCreateModelFromJson<MyModel>(
"viewModel");
this.EditFromModel(viewModel);
return
this.JsonResponse(
this.T("Model updated successfuly."),
true);
}
catch (Exception ex)
{
this.Logger.Error(ex, "Error while updating model.");
return this.JsonResponse(this.T("Error"), false);
}
}
Called from JS:
function saveViewModel() {
$.post(
'#Url.Action("EditAjax")',
{
__RequestVerificationToken: '#Html.AntiForgeryTokenValueOrchard()',
viewModel: ko.mapping.toJSON(viewModel)
},
function (data) {
// response
});
}
Used additional library for deserializing/serializing JSON: http://www.nuget.org/packages/Newtonsoft.Json