For a project that I am working on, I'm trying to replicate a JSON file that was created with JavaScript in C#. For this project I have to label images before I can run them through a Neural Network, and to annotate those images I use via. The resulting JSON file looks like this.
"Dog.png173732": {
"filename": "Dog.png",
"size": 173732,
"regions": [
{
"shape_attributes": {
"name": "polygon",
"all_points_x": [
189,
192,
229,
230
],
"all_points_y": [
2,
148,
148,
2
]
},
"region_attributes": {
"Animal": "Dog"
}
}
],
"file_attributes": {}
},
To replicate this in C#, I created a class with multiple getters and setters, while using the Nuget package JSON.Net, to serialize my JSON.
public class Animal
{
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string Filename { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public int? Size { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public List<Animal> Regions { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public List<Animal> Shape_attributes { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string Name { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public List<int> All_points_x { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public List<int> All_points_y { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public List<Animal> Region_attributes { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string Animal { get; set; }
public void CreateJSON()
{
string output = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile) +
#"\source\repos\Testing\";
var root = new Animal()
{
Filename = "Dog.png",
Size = 173732,
Regions = new List<Animal>()
{
new Animal()
{
Size = null,
Shape_attributes = new List<Animal>()
{
new Animal()
{
Name = "polygon",
All_points_x = All_points_x,
All_points_y = All_points_y
}
},
Region_attributes = new List<Animal>()
{
new Animal()
{
Animal = "Dog"
}
}
}
}
};
var json = JsonConvert.SerializeObject(root, new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
});
File.WriteAllText(output + "testing.json", json);
}
Once I execute the following code, my output is as follows.
{
"filename": "Dog.png",
"size": 173732,
"regions": [
{
"shape_attributes": [
{
"name": "polygon",
"all_points_x": [
389,
43
],
"all_points_y": [
33,
215
]
}
],
"region_attributes": [
{
"animal": "Dog"
}
]
}
]
}
How can I adjust my code to better replicated via's Json file? Is there a better way that I could be doing things?
How about something like this...
First I created classes for each of the inner bits of your structure:
public class RegionAttributes
{
public string Animal { get; set; }
}
public class ShapeAttributes
{
public string name { get; set; }
public List<int> all_points_x { get; set; }
public List<int> all_points_y { get; set; }
}
public class Region
{
public ShapeAttributes shape_attributes { get; set; }
public RegionAttributes region_attributes { get; set; }
}
public class Thing
{
public string filename { get; set; }
public int size { get; set; }
public List<Region> regions { get; set; }
public dynamic file_attributes { get; set; }
}
You should be able to see that the hierarchy of these classes matches the hierarchy of your JSON.
Then I initialize one of these Things:
var thing = new Dictionary<string, Thing>
{
{
"Dog.png173732", new Thing
{
filename = "Dog.png",
size = 173732,
regions = new List<Region>
{
new Region
{
shape_attributes = new ShapeAttributes
{
name = "polygon",
all_points_x = new List<int> {189, 192, 229, 230},
all_points_y = new List<int> {2, 148, 148, 2},
},
region_attributes = new RegionAttributes
{
Animal = "dog",
}
}
},
file_attributes = new object()
}
}
};
Again, you can see the similarity of the structure in the code to the structure of the JSON. Finally, I do this (using the Newtonsoft JSON package):
var result = JsonConvert.SerializeObject(thing, Formatting.Indented);
This results in this string:
{
"Dog.png173732": {
"filename": "Dog.png",
"size": 173732,
"regions": [
{
"shape_attributes": {
"name": "polygon",
"all_points_x": [
189,
192,
229,
230
],
"all_points_y": [
2,
148,
148,
2
]
},
"region_attributes": {
"Animal": "dog"
}
}
],
"file_attributes": {}
}
}
I think that's a match. You'll probably want to use attributes to get C#-ish names in the C# code and JSON-ish names in the JSON output. But, there you go...
You were quite close to it, but your structure was missing. There are a couple of things you could look at, for example, the NamingStrategy that the json object is using is called SnakeCase and NewtonSoft has a default implementation for this strategy.
To set the default convention, you could make it available through:
JsonConvert.DefaultSettings = () => {
return new JsonSerializerSettings() {
ContractResolver = new DefaultContractResolver {
NamingStrategy = new SnakeCaseNamingStrategy()
},
Formatting = Formatting.Indented
};
};
This then allows you to use normal C# naming conventions for your poco structure, which could look like this:
public class Root : Dictionary<string, Animal> {
}
public class Animal {
public string Filename { get; set; }
public long Size { get;set; }
public IList<Region> Regions { get;set; }
[JsonExtensionData]
public IDictionary<string, object> Properties { get;set; }
}
public class Region {
public ShapeAttribute ShapeAttributes { get; set; }
public RegionAttribute RegionAttributes { get; set; }
}
public class ShapeAttribute {
public string Name { get; set; }
public IList<int> AllPointsX { get; set; }
public IList<int> AllPointsY { get; set; }
}
public class RegionAttribute {
[JsonProperty("Animal")]
public string Animal { get;set; }
}
This has 2 caveats, the Animal property inside the RegionAttribute class, should be defined directly (as it capitalized), and for all remaining unspecified properties (like file_attributes) I added an IDictionary<string, object> Properties that would hold all non-specified properties on the Animal object.
I provided a sample based on your data in this dotnetfiddle
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 am new to c# and json.net.
I have a json configuration file and try to parse it to objects. But how can i map the relations correctly in the objects?
Currently the property in project loop is null.
And can the objects map "automatically" without mapping each property name/value?
I can also change the json!
configuration.json:
{
"debug": true,
"log": "database",
"projects": [
{
"name": "Name 1",
"showInfo": false,
"ranges": [
[
5,
6
],
[
9,
10
],
[
15,
20
]
],
"additional": [
{
"name": "subName 1",
"parameter": "ID"
},
{
"name": "subName 2",
"parameter": "ID2"
}
]
},
{
"name": "Name 2",
"showInfo": false,
"ranges": [
[
99,
100
]
]
},
{
"name": "Name 3",
"showInfo": false,
"ranges": [
[
44,
45
]
]
},
{
"name": "Name 4",
"showInfo": false,
"ranges": [
[
12,
14
]
],
"additional": [
{
"name": "subName xy",
"parameter": "ID"
}
]
}
]
}
my try to parse:
Configuration configuration = new Configuration();
JObject jObject = JObject.Parse(File.ReadAllText(filePath));
if (jObject.ContainsKey("debug"))
{
configuration.Debug = (bool) jObject["debug"];
}
if (jObject.ContainsKey("log"))
{
configuration.Log = (string) jObject["log"];
}
//loop projects
JToken projects = jObject["projects"];
foreach (JToken child in projects.Children())
{
var property = child as JProperty;
if (property != null)
{
var test = property.Name;
var test2 = property.Value;
}
}
the objects:
public class Configuration
{
public bool Debug { get; set; } = false;
public string Log { get; set; }
// this is propably wrong
public Dictionary<string, Dictionary<string, Project>> Projects { get; set; }
}
public class Project
{
public string name { get; set; }
public bool showInfo{ get; set; }
// wrong?
public int[,] ranges { get; set; }
// wrong?
public Additional[] Additional{ get; set; }
}
public class Additional
{
public string Name{ get; set; }
public string Parameter { get; set; }
}
You don't need a JObject at all json files can be desterilized to objects it's much more efficient because you don't create unneeded objects.
You Config class is just wrong
public class Configuration
{
public bool Debug { get; set; }
public string Log { get; set; }
public Project[] Projects { get; set; }
}
public class Project
{
public string Name { get; set; }
public bool ShowInfo { get; set; }
public int[][] Ranges { get; set; }
public Additional[] Additional { get; set; }
}
public class Additional
{
public string Name { get; set; }
public string Parameter { get; set; }
}`
Should look like this.
And then use. JsonConvert.DeserializeObject<Configuration>(json); To get the object.
If you have Visual studio it has this cool feature called paste special where you can just past your json and it will create a proper class for deserialization. It's under Edit-> Paste special-> Paste json as class
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);
}
I am trying to get a specific part from a JSON response string.
Here is the JSON code :
{
"metadata": {
"provider": "Oxford University Press"
},
"results": [
{
"id": "door",
"language": "en",
"lexicalEntries": [
{
"entries": [
{
"homographNumber": "000",
"senses": [
{
"definitions": [
"a hinged, sliding, or revolving barrier at the entrance to a building, room, or vehicle, or in the framework of a cupboard"
],
"id": "m_en_gbus0290920.005",
"subsenses": [
{
"definitions": [
"a doorway"
],
"id": "m_en_gbus0290920.008"
},
{
"definitions": [
"used to refer to the distance from one building in a row to another"
],
"id": "m_en_gbus0290920.009"
}
]
}
]
}
],
"language": "en",
"lexicalCategory": "Noun",
"text": "door"
}
],
"type": "headword",
"word": "door"
}
]
}
I am trying to get this code
"definitions": [
"a hinged, sliding, or revolving barrier at the entrance to a building, room, or vehicle, or in the framework of a cupboard"
in a string
Here is my code:
string language = "en";
string word_id = textBox1.Text.ToLower();
String url = "https://od-api.oxforddictionaries.com:443/api/v1/entries/" + language + "/" + word_id+"/definitions";
HttpClient client = new HttpClient();
client.BaseAddress = new Uri(url);
client.DefaultRequestHeaders.Add("app_id", app_Id);
client.DefaultRequestHeaders.Add("app_key", app_Key);
HttpResponseMessage response = client.GetAsync(url).Result;
if (response.IsSuccessStatusCode)
{
var result = response.Content.ReadAsStringAsync().Result;
var s = JsonConvert.DeserializeObject(result);
textBox2.Text = s.ToString();
}
else MessageBox.Show(response.ToString());
I am using C#.
C# Classes
Step one is to create some classes to allow us to represent the data in C#. If you don't have them... QuickType does that.
namespace QuickType
{
using System;
using System.Net;
using System.Collections.Generic;
using Newtonsoft.Json;
public partial class GettingStarted
{
[JsonProperty("metadata")]
public Metadata Metadata { get; set; }
[JsonProperty("results")]
public Result[] Results { get; set; }
}
public partial class Result
{
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("language")]
public string Language { get; set; }
[JsonProperty("lexicalEntries")]
public LexicalEntry[] LexicalEntries { get; set; }
[JsonProperty("type")]
public string Type { get; set; }
[JsonProperty("word")]
public string Word { get; set; }
}
public partial class LexicalEntry
{
[JsonProperty("entries")]
public Entry[] Entries { get; set; }
[JsonProperty("language")]
public string Language { get; set; }
[JsonProperty("lexicalCategory")]
public string LexicalCategory { get; set; }
[JsonProperty("text")]
public string Text { get; set; }
}
public partial class Entry
{
[JsonProperty("homographNumber")]
public string HomographNumber { get; set; }
[JsonProperty("senses")]
public Sense[] Senses { get; set; }
}
public partial class Sense
{
[JsonProperty("definitions")]
public string[] Definitions { get; set; }
[JsonProperty("id")]
public string Id { get; set; }
[JsonProperty("subsenses")]
public Subsense[] Subsenses { get; set; }
}
public partial class Subsense
{
[JsonProperty("definitions")]
public string[] Definitions { get; set; }
[JsonProperty("id")]
public string Id { get; set; }
}
public partial class Metadata
{
[JsonProperty("provider")]
public string Provider { get; set; }
}
public partial class GettingStarted
{
public static GettingStarted FromJson(string json) => JsonConvert.DeserializeObject<GettingStarted>(json, Converter.Settings);
}
public static class Serialize
{
public static string ToJson(this GettingStarted self) => JsonConvert.SerializeObject(self, Converter.Settings);
}
public class Converter
{
public static readonly JsonSerializerSettings Settings = new JsonSerializerSettings
{
MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
DateParseHandling = DateParseHandling.None,
};
}
}
Deserialize
You'll notice that we also have converters to serialize and deserialize generated for us. The deserialize bit is as simple as:
var result = JsonConvert.DeserializeObject<GettingStarted>(json);
Use
Start from the result variable and use dots to find your way down to your item...
var description = result.results.lexicalEntries.First()
.entries.First()
.senses.First()
.definitions.First();
All of those First() calls are due to each of these parts of the data being arrays. You'll need to reference System.Linq for that. You will want to read a little around what to do if you have more than one, or less than one, at any of those levels (you may need to work with collections, or perform more traversal).
You can create a class whose properties are the names of the JSON you are trying to parse. That way you can deserialize the JSON into an instance of that class and pull whatever property you need. You'll need to use the Newtonsoft.Json package.
Example class:
public class YourClass
{
public string propertyA { get; set; }
public string propertyB { get; set; }
}
And then in your main code:
YourClass yourClass = new YourClass();
try
{
yourClass = JsonConvert.DeserializeObject<YourClass>(yourJsonStringGoesHere);
}
catch (Exception ex)
{
//log exception 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.