Related
I am writing a tool to work with resume.json files (project) and am creating a Json Schema to validate user input. I'm trying to automate this with Json.Net.Schema but the output always makes all properties required, regardless of whether the properties have the [Required] or [JsonRequired] attributes.
Schema Generation Code
var generator = new JSchemaGenerator
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
SchemaIdGenerationHandling = SchemaIdGenerationHandling.TypeName
};
var schema = generator.Generate(typeof(Resume));
var sb = new StringBuilder();
schema.WriteTo(new JsonTextWriter(
new IndentedTextWriter(
new StringWriter(sb),
" ")
)
{
Formatting = Formatting.Indented,
IndentChar = ' ', Indentation = 2,
QuoteName = true
}, new JSchemaWriterSettings
{
Version = SchemaVersion.Draft7
});
File.WriteAllText("E:\\resume.schema", sb.ToString());
Resume Class (and children)
public class Resume
{
[Required]
public Basics Basics { get; set; }
public Work[] Work { get; set; }
public Volunteer[] Volunteer { get; set; }
public Education[] Education { get; set; }
public Award[] Awards { get; set; }
public Publication[] Publications { get; set; }
public Skill[] Skills { get; set; }
public Language[] Languages { get; set; }
public Interest[] Interests { get; set; }
public Reference[] References { get; set; }
}
public class Award
{
[Required]
public string Title { get; set; }
public string Date { get; set; }
public string Awarder { get; set; }
public string Summary { get; set; }
}
public class Basics
{
[Required]
public string Name { get; set; }
public string Label { get; set; }
public Uri Picture { get; set; }
public string Email { get; set; }
public string Phone { get; set; }
public string Website { get; set; }
public string Summary { get; set; }
public Location Location { get; set; }
public Profile[] Profiles { get; set; }
}
public class Education
{
[Required]
public string Institution { get; set; }
public string Area { get; set; }
public string StudyType { get; set; }
public string StartDate { get; set; }
public string EndDate { get; set; }
public string Gpa { get; set; }
public string[] Courses { get; set; }
}
public class Interest
{
[Required]
public string Name { get; set; }
public string[] Keywords { get; set; }
}
public class Language
{
[Required]
public string language { get; set; }
[Required]
public string Fluency { get; set; }
}
public class Location
{
public string Address { get; set; }
[Required]
public string PostalCode { get; set; }
[Required]
public string City { get; set; }
[Required]
public string CountryCode { get; set; }
public string Region { get; set; }
}
public class Profile
{
[Required]
public string Network { get; set; }
[Required]
public string Username { get; set; }
[Required]
public string Url { get; set; }
}
public class Publication
{
[Required]
public string Name { get; set; }
public string Publisher { get; set; }
public string ReleaseDate { get; set; }
public string Website { get; set; }
public string Summary { get; set; }
}
public class Reference
{
[Required]
public string Name { get; set; }
public string reference { get; set; }
}
public class Skill
{
[Required]
public string Name { get; set; }
[Required]
public string Level { get; set; }
public string[] Keywords { get; set; }
}
public class Volunteer
{
[Required]
public string Organization { get; set; }
[Required]
public string Position { get; set; }
public string Website { get; set; }
public string StartDate { get; set; }
public string EndDate { get; set; }
public string Summary { get; set; }
public string[] Highlights { get; set; }
}
public class Work
{
[Required]
public string Company { get; set; }
[Required]
public string Position { get; set; }
public string Website { get; set; }
[Required]
public string StartDate { get; set; }
public string EndDate { get; set; }
public string Summary { get; set; }
public string[] Highlights { get; set; }
}
Current Output
{
"$schema": "http://json-schema.org/draft-07/schema#",
"$id": "Resume",
"definitions": {
"Award": {
"$id": "Award",
"type": [
"object",
"null"
],
"properties": {
"title": {
"type": "string"
},
"date": {
"type": [
"string",
"null"
]
},
"awarder": {
"type": [
"string",
"null"
]
},
"summary": {
"type": [
"string",
"null"
]
}
},
"required": [
"title",
"date",
"awarder",
"summary"
]
},
"Basics": {
"$id": "Basics",
"type": "object",
"properties": {
"name": {
"type": "string"
},
"label": {
"type": [
"string",
"null"
]
},
"picture": {
"type": [
"string",
"null"
],
"format": "uri"
},
"email": {
"type": [
"string",
"null"
]
},
"phone": {
"type": [
"string",
"null"
]
},
"website": {
"type": [
"string",
"null"
]
},
"summary": {
"type": [
"string",
"null"
]
},
"location": {
"$id": "Location",
"type": [
"object",
"null"
],
"properties": {
"address": {
"type": [
"string",
"null"
]
},
"postalCode": {
"type": "string"
},
"city": {
"type": "string"
},
"countryCode": {
"type": "string"
},
"region": {
"type": [
"string",
"null"
]
}
},
"required": [
"address",
"postalCode",
"city",
"countryCode",
"region"
]
},
"profiles": {
"$id": "Profile[]",
"type": [
"array",
"null"
],
"items": {
"$id": "Profile",
"type": [
"object",
"null"
],
"properties": {
"network": {
"type": "string"
},
"username": {
"type": "string"
},
"url": {
"type": "string"
}
},
"required": [
"network",
"username",
"url"
]
}
}
},
"required": [
"name",
"label",
"picture",
"email",
"phone",
"website",
"summary",
"location",
"profiles"
]
},
"Education": {
"$id": "Education",
"type": [
"object",
"null"
],
"properties": {
"institution": {
"type": "string"
},
"area": {
"type": [
"string",
"null"
]
},
"studyType": {
"type": [
"string",
"null"
]
},
"startDate": {
"type": [
"string",
"null"
]
},
"endDate": {
"type": [
"string",
"null"
]
},
"gpa": {
"type": [
"string",
"null"
]
},
"courses": {
"$id": "String[]",
"type": [
"array",
"null"
],
"items": {
"type": [
"string",
"null"
]
}
}
},
"required": [
"institution",
"area",
"studyType",
"startDate",
"endDate",
"gpa",
"courses"
]
},
"Interest": {
"$id": "Interest",
"type": [
"object",
"null"
],
"properties": {
"name": {
"type": "string"
},
"keywords": {
"$id": "String[]",
"type": [
"array",
"null"
],
"items": {
"type": [
"string",
"null"
]
}
}
},
"required": [
"name",
"keywords"
]
},
"Language": {
"$id": "Language",
"type": [
"object",
"null"
],
"properties": {
"language": {
"type": "string"
},
"fluency": {
"type": "string"
}
},
"required": [
"language",
"fluency"
]
},
"Location": {
"$ref": "Location"
},
"Profile": {
"$ref": "Profile"
},
"Publication": {
"$id": "Publication",
"type": [
"object",
"null"
],
"properties": {
"name": {
"type": "string"
},
"publisher": {
"type": [
"string",
"null"
]
},
"releaseDate": {
"type": [
"string",
"null"
]
},
"website": {
"type": [
"string",
"null"
]
},
"summary": {
"type": [
"string",
"null"
]
}
},
"required": [
"name",
"publisher",
"releaseDate",
"website",
"summary"
]
},
"Reference": {
"$id": "Reference",
"type": [
"object",
"null"
],
"properties": {
"name": {
"type": "string"
},
"reference": {
"type": [
"string",
"null"
]
}
},
"required": [
"name",
"reference"
]
},
"Skill": {
"$id": "Skill",
"type": [
"object",
"null"
],
"properties": {
"name": {
"type": "string"
},
"level": {
"type": "string"
},
"keywords": {
"$id": "String[]",
"type": [
"array",
"null"
],
"items": {
"type": [
"string",
"null"
]
}
}
},
"required": [
"name",
"level",
"keywords"
]
},
"Volunteer": {
"$id": "Volunteer",
"type": [
"object",
"null"
],
"properties": {
"organization": {
"type": "string"
},
"position": {
"type": "string"
},
"website": {
"type": [
"string",
"null"
]
},
"startDate": {
"type": [
"string",
"null"
]
},
"endDate": {
"type": [
"string",
"null"
]
},
"summary": {
"type": [
"string",
"null"
]
},
"highlights": {
"$id": "String[]",
"type": [
"array",
"null"
],
"items": {
"type": [
"string",
"null"
]
}
}
},
"required": [
"organization",
"position",
"website",
"startDate",
"endDate",
"summary",
"highlights"
]
},
"Work": {
"$id": "Work",
"type": [
"object",
"null"
],
"properties": {
"company": {
"type": "string"
},
"position": {
"type": "string"
},
"website": {
"type": [
"string",
"null"
]
},
"startDate": {
"type": "string"
},
"endDate": {
"type": [
"string",
"null"
]
},
"summary": {
"type": [
"string",
"null"
]
},
"highlights": {
"$id": "String[]",
"type": [
"array",
"null"
],
"items": {
"type": [
"string",
"null"
]
}
}
},
"required": [
"company",
"position",
"website",
"startDate",
"endDate",
"summary",
"highlights"
]
}
},
"type": "object",
"properties": {
"basics": {
"$ref": "Basics"
},
"work": {
"$id": "Work[]",
"type": [
"array",
"null"
],
"items": {
"$ref": "Work"
}
},
"volunteer": {
"$id": "Volunteer[]",
"type": [
"array",
"null"
],
"items": {
"$ref": "Volunteer"
}
},
"education": {
"$id": "Education[]",
"type": [
"array",
"null"
],
"items": {
"$ref": "Education"
}
},
"awards": {
"$id": "Award[]",
"type": [
"array",
"null"
],
"items": {
"$ref": "Award"
}
},
"publications": {
"$id": "Publication[]",
"type": [
"array",
"null"
],
"items": {
"$ref": "Publication"
}
},
"skills": {
"$id": "Skill[]",
"type": [
"array",
"null"
],
"items": {
"$ref": "Skill"
}
},
"languages": {
"$id": "Language[]",
"type": [
"array",
"null"
],
"items": {
"$ref": "Language"
}
},
"interests": {
"$id": "Interest[]",
"type": [
"array",
"null"
],
"items": {
"$ref": "Interest"
}
},
"references": {
"$id": "Reference[]",
"type": [
"array",
"null"
],
"items": {
"$ref": "Reference"
}
}
},
"required": [
"basics",
"work",
"volunteer",
"education",
"awards",
"publications",
"skills",
"languages",
"interests",
"references"
]
}
How do I get the schema generator to honor the Required attributes?
JSchemaGenerator has a property DefaultRequired:
Gets or sets the default required state of schemas.
For some reason, the default value for this property is Required.AllowNull, as shown in the source:
public JSchemaGenerator()
{
_schemaReferenceHandling = SchemaReferenceHandling.Objects;
_defaultRequired = Required.AllowNull;
}
If you change it to Required.Default, only those properties explicitly marked as required, e.g. with [Required] or [JsonProperty(Required = Required.Always)], will be listed as required in the schema:
var generator = new JSchemaGenerator
{
ContractResolver = new CamelCasePropertyNamesContractResolver(),
SchemaIdGenerationHandling = SchemaIdGenerationHandling.TypeName,
DefaultRequired = Required.Default,
};
The default value for DefaultRequired isn't documented, but probably should be. You might open an issue with Newtonsoft requesting a clarification to the documentation.
Demo fiddle here.
I have a JSON that contains a list of types. These types have some name and some fields.
Fields have a property of dataType and if it's value is object, it refers to a another type. That type could be found by its name specified in referenceType property.
There is also a property named parentType which means the type is a child of the parentType and it contains some additional properties, but have to be considered as an object of parentType only.
I am trying to process this JSON to get all the nested property names for all the types present in the array.
{
"types": [
{
"name": "User1",
"fields": [
{
"name": "name",
"dataType": "string"
},
{
"name": "address",
"dataType": "object",
"referenceType": "Address",
"isArray": true
},
{
"name": "weeklyRoles",
"dataType": "object",
"isArray": true,
"referenceType": "Role"
}
]
},
{
"name": "User2",
"fields": [
{
"name": "name",
"dataType": "string"
},
{
"name": "address",
"dataType": "object",
"referenceType": "Address",
"isArray": true
}
]
},
{
"name": "Address",
"fields": [
{
"name": "AddressLine1",
"dataType": "string"
},
{
"name": "AddressLine2",
"dataType": "string"
}
]
},
{
"name": "BusinessAddress",
"parentType": "Address",
"fields": [
{
"name": "headquarters",
"dataType": "string"
}
]
},
{
"name": "ServiceAddress",
"parentType": "Address",
"fields": [
{
"name": "servicePartner",
"dataType": "string"
},
{
"name": "serviceType",
"dataType": "string"
}
]
},
{
"name": "Role",
"fields": [
{
"name": "roleName",
"dataType": "string"
},
{
"name": "accessCountsObj1",
"dataType": "object",
"referenceType": "Role2"
}
]
},
{
"name": "Role2",
"fields": [
{
"name": "roleName2",
"dataType": "string"
},
{
"name": "accessCountsObj2",
"dataType": "object",
"referenceType": "Role3"
}
]
},
{
"name": "Role3",
"fields": [
{
"name": "roleName3",
"dataType": "string"
},
{
"name": "accessCountsObj3",
"dataType": "object",
"referenceType": "Role4"
}
]
},
{
"name": "Role4",
"fields": [
{
"name": "roleName4",
"dataType": "string"
}
]
}
]
}
Pattern in which I am expecting the result is <typeName>;<fieldName>.<nestedFieldName>
Expected Output
[
"User1;address.AddressLine1",
"User1;address.AddressLine2",
"User1;address.headquarters",
"User1;address.servicePartner",
"User1;address.serviceType",
"User1;weeklyRoles.roleName",
"User1;weeklyRoles.accessCountsObj1.roleName2",
"User1;weeklyRoles.accessCountsObj1.accessCountsObj2.roleName3",
"User1;weeklyRoles.accessCountsObj1.accessCountsObj2.accessCountsObj3.roleName4",
"User2;address.AddressLine1",
"User2;address.AddressLine2",
"User2;address.headquarters",
"User2;address.servicePartner",
"User2;address.serviceType",
"Role;accessCountsObj1.roleName2",
"Role;accessCountsObj1.accessCountsObj2.roleName3",
"Role;accessCountsObj1.accessCountsObj2.accessCountsObj3.roleName4",
"Role2;accessCountsObj2.roleName3",
"Role2;accessCountsObj2.accessCountsObj3.roleName4",
]
I have tried to write a recursive function to process it but it is not giving me the expected result and also does not have terminating condition.
public IList<string> GetKeys(JArray types, string parentType = null)
{
var nestedKeys = new List<string>();
foreach (var type in types)
{
var fields = type[Constants.Fields].ToObject<List<JObject>>();
var typeName = type.Value<string>("name");
var nestedKeyBuilder = new StringBuilder($"{typeName};");
if (!string.IsNullOrEmpty(parentType))
{
nestedKeyBuilder = new StringBuilder($"{parentType};");
}
foreach (var field in fields)
{
var datatype = field.Value<string>("dataType");
if (string.Equals(datatype,"object"))
{
var fieldName = field.Value<string>("name");
var referenceTypeName = field.Value<string>("referenceType");
var referenceTypeObject = types.Where(t => string.Equals(t.Value<string>("name"), referenceTypeName))?.First();
if (referenceTypeObject != null)
{
var refTypeFields = referenceTypeObject["fields"].ToObject<List<JObject>>();
foreach (var refTypeField in refTypeFields)
{
var refTypeFieldName = refTypeField.Value<string>("name");
var refTypeDataType = refTypeField.Value<string>("dataType");
var refTypeReferenceTypeName = refTypeField.Value<string>("referenceType");
if (string.Equals(refTypeDataType, "object") && string.Equals(refTypeReferenceTypeName, currentReferenceType))
{
var refTypeNestedKeys = GetKeys(types, typeName);
nestedKeys.AddRange(refTypeNestedKeys);
}
else
{
nestedKeyBuilder.Append($"{fieldName}.{refTypeFieldName}");
nestedKeys.Add(nestedKeyBuilder.ToString());
}
}
}
}
}
}
return nestedKeys;
}
There is a NuGet that you can use to handle JSON files.
Search for Newtonsoft.Json
https://www.newtonsoft.com/json
All your problems should be solved with that
You can use Newtonsoft library to do this.
This is your POCO class.
{
public string name { get; set; }
public string dataType { get; set; }
public string referenceType { get; set; }
public bool? isArray { get; set; }
}
public class Type
{
public string name { get; set; }
public List<Field> fields { get; set; }
public string parentType { get; set; }
}
public class RootObject
{
public List<Type> types { get; set; }
}
and write the function to DeserializeObject
[TestMethod]
public void Read()
{
var sample1 = #"X:\JsonFilePath\data.json";
var jsonString=File.ReadAllText(sample1);
var result =JsonConvert.DeserializeObject<RootObject>(jsonString);
Assert.IsNotNull(result);
}
Use newtonsoft JSON to Deseriliaze the JSON string.
JSON.Deserialize<IEnumerable<Type>>(jsonString);
This should give you an IEnumerable to process it however you want. Types is the class you create with the JSON properties as class properties. You can use something like this
NOTE: Type and Field are very vague names. Type is a c# class and therefore you should not use it to create a class of your own. You will face ambiguous errors and you will need to qualify the namespace in full to use your class. Strongly suggesting to name it something else and use the attributes to map it to the JSON string.
[JsonObject(Title="People")]
public class Type
{
[JsonProperty("name")]
string Name{ get; set; }
[JsonProperty("fields")]
Field FieldValue[]{ get; set; }
}
I am trying to assign this object as follows:
RootObject aaa = new RootObject() {
"word": "example",
"results": [
{
"definition": "a representative form or pattern",
"partOfSpeech": "noun",
"synonyms": [
"model"
],
"typeOf": [
"representation",
"internal representation",
"mental representation"
],
"hasTypes": [
"prefiguration",
"archetype",
"epitome",
"guide",
"holotype",
"image",
"loadstar",
"lodestar",
"microcosm",
"original",
"paradigm",
"pilot",
"prototype",
"template",
"templet",
"type specimen"
],
"derivation": [
"exemplify"
],
"examples": [
"I profited from his example"
]
},
{
"definition": "something to be imitated",
"partOfSpeech": "noun",
"synonyms": [
"exemplar",
"good example",
"model"
],
"typeOf": [
"ideal"
],
"hasTypes": [
"pacemaker",
"pattern",
"beauty",
"prodigy",
"beaut",
"pacesetter"
],
"derivation": [
"exemplify",
"exemplary"
]
},
{
"definition": "an occurrence of something",
"partOfSpeech": "noun",
"synonyms": [
"case",
"instance"
],
"typeOf": [
"happening",
"natural event",
"occurrence",
"occurrent"
],
"hasTypes": [
"clip",
"mortification",
"piece",
"time",
"humiliation",
"bit"
],
"derivation": [
"exemplify"
],
"examples": [
"but there is always the famous example of the Smiths"
]
},
{
"definition": "an item of information that is typical of a class or group",
"partOfSpeech": "noun",
"synonyms": [
"illustration",
"instance",
"representative"
],
"typeOf": [
"information"
],
"hasTypes": [
"excuse",
"apology",
"specimen",
"case in point",
"sample",
"exception",
"quintessence",
"precedent"
],
"derivation": [
"exemplify",
"exemplary"
],
"examples": [
"this patient provides a typical example of the syndrome",
"there is an example on page 10"
]
},
{
"definition": "punishment intended as a warning to others",
"partOfSpeech": "noun",
"synonyms": [
"deterrent example",
"lesson",
"object lesson"
],
"typeOf": [
"monition",
"admonition",
"word of advice",
"warning"
],
"derivation": [
"exemplary"
],
"examples": [
"they decided to make an example of him"
]
},
{
"definition": "a task performed or problem solved in order to develop skill or understanding",
"partOfSpeech": "noun",
"synonyms": [
"exercise"
],
"typeOf": [
"lesson"
],
"examples": [
"you must work the examples at the end of each chapter in the textbook"
]
}
],
"syllables": {
"count": 3,
"list": [
"ex",
"am",
"ple"
]
},
"pronunciation": {
"all": "ɪɡ'zæmpəl"
}
}
Here are the classes I defined:
public class Result
{
public string definition { get; set; }
public string partOfSpeech { get; set; }
public List<string> synonyms { get; set; }
public List<string> typeOf { get; set; }
public List<string> hasTypes { get; set; }
public List<string> derivation { get; set; }
public List<string> examples { get; set; }
}
public class Syllables
{
public int count { get; set; }
public List<string> list { get; set; }
}
public class Pronunciation
{
public string all { get; set; }
}
public class RootObject
{
public string word { get; set; }
public List<Result> results { get; set; }
public Syllables syllables { get; set; }
public Pronunciation pronunciation { get; set; }
}
I'm getting syntax errors starting on the first line with "word".
Is there a way I can debug this or at least find out what is causing the problem?
Try
RootObject aaa = JsonConvert.DeserializeObject<RootObject>(
put_your_string_from_the_question);
Download Json.Net from nuget.org
You simply cannot assign JSON object to C# Object. You need to assign properties of your class and DeSerialize that to JSON format.
in your case you should do like this way:
var roorObj= new RootObject()
{
word ="your word",
//
//
}
Then to get the JOSN string, use this:
RootObject aaa = JsonConvert.DeserializeObject<RootObject>(roorObj);
Hope you will get some idea to play with C# object and JSON.
I have the following json coming through the elasticsearch:
{
"_index": "data-2016-01-14",
"_type": "type-data",
"_id": "AVJBBNG-TE8FYIA1rf1p",
"_score": 1,
"_source": {
"#message": {
"timestamp": 1452789770326461200,
"eventID": 1452789770326461200,
"eventName": "New",
"Price": "38.34",
"Qty": 100,
"statistic_LatencyValue_ns": 1142470,
"statistic_LatencyViolation": false,
"statistic_LossViolation": false
},
"#timestamp": "2016-01-14T16:42:50.326Z",
"#fields": {
"timestamp": "1452789770326"
}
},
"fields": {
"#timestamp": [
1452789770326
]
}
}
I'm using Nest to try to get the eventName data i created the class and marked the property:
public class ElasticTest
{
[ElasticProperty(Type = FieldType.Nested)]
public string eventName { get; set; }
}
But the following query is returning 0 results, what am i doing wrong?
var result = client.Search<CorvilTest>(s => s
.From(0)
.Size(10000)
.Query(x => x
.Term(e => e.eventName,"New"))
);
var r = result.Documents;
Mapping definition:
{
"data-2016-01-14": {
"mappings": {
"type-data": {
"properties": {
"#fields": {
"properties": {
"timestamp": {
"type": "string"
}
}
},
"#message": {
"properties": {
"OrderQty": {
"type": "long"
},
"Price": {
"type": "string"
},
"eventID": {
"type": "long"
},
"eventName": {
"type": "string"
},
"statistic_LatencyValue_ns": {
"type": "long"
},
"statistic_LatencyViolation": {
"type": "boolean"
},
"statistic_LossViolation": {
"type": "boolean"
},
"timestamp": {
"type": "long"
}
}
},
"#timestamp": {
"type": "date",
"format": "dateOptionalTime"
}
}
}
}
}
}
I see that the field #message.eventName is using a standard analyzer which means that its value is lower-cased and split at word boundaries before indexing. Hence the value "new" is indexed and not "New". Read more about it here. You need to be mindful about this fact when using a Term Query. Another thing is that the field eventName is not of nested type. So the code below should work for you.
var result = client.Search<CorvilTest>(s => s
.From(0)
.Size(10000)
.Query(x => x
.Term(e => e.Message.EventName, "new"))); // Notice I've used "new" and not "New"
var r = result.Documents;
For the above code to work the definition of CorvilTest class should be something like below:
public class CorvilTest
{
[ElasticProperty(Name = "#message")]
public Message Message { get; set; }
/* Other properties if any */
}
public class Message
{
[ElasticProperty(Name = "eventName")]
public string EventName { get; set; }
}
The task I have is to parse JSON into objects which can then create a form. This form can have sub-forms within it and it is this step I am having difficulty with.
Consider this JObject which is a representation of the sub-form and, because the main form has already been deserialized, is now passed as a JObject:
{
"3705": {
"type": "radioGroup",
"label": "Loft Insulation Applicable",
"default_value": null,
"order": "2",
"required": "false",
"security": "false",
"option": null,
"child": [
{
"type": "radio",
"label": "No",
"order": "3"
},
{
"type": "radio",
"label": "Yes",
"order": "4"
}
]
},
"3708": {
"type": "input",
"label": "Existing Depth (mm)",
"default_value": null,
"order": "5",
"required": "false",
"security": "false",
"option": null
},
"3709": {
"type": "input",
"label": "Required Depth (mm)",
"default_value": null,
"order": "6",
"required": "false",
"security": "false",
"option": null
},
"3715": {
"type": "radioGroup",
"label": "Total Pipework Meterage",
"default_value": null,
"order": "16",
"required": "false",
"security": "false",
"option": null,
"child": [
{
"type": "radio",
"label": "15 mm",
"order": "17"
},
{
"type": "radio",
"label": "22 mm",
"order": "18"
},
{
"type": "radio",
"label": "28 mm",
"order": "19"
}
]
},
"3719": {
"type": "formLabel",
"label": "Loft Access Requirements",
"default_value": null,
"order": "20",
"required": "false",
"security": "false",
"option": null
},
"3720": {
"type": "radioGroup",
"label": "Crawlers",
"default_value": null,
"order": "21",
"required": "false",
"security": "false",
"option": null,
"child": [
{
"type": "radio",
"label": "No",
"order": "22"
},
{
"type": "radio",
"label": "Yes",
"order": "23"
}
]
},
"3723": {
"type": "radioGroup",
"label": "Cavity Ladders for Loft",
"default_value": null,
"order": "24",
"required": "false",
"security": "false",
"option": null,
"child": [
{
"type": "radio",
"label": "No",
"order": "25"
},
{
"type": "radio",
"label": "Yes",
"order": "26"
}
]
},
"3726": {
"type": "image",
"label": "Loft Photos",
"default_value": null,
"order": "27",
"required": "false",
"security": "false",
"option": null
}
}
I am trying to Deserialize it to a list of objects of types defined in this class:
public class DBFormField
{
public string type { get; set; }
public string label { get; set; }
public string default_value { get; set; }
public string order { get; set; }
public string required { get; set; }
public DBFormFieldOption option = new DBFormFieldOption();
public List<DBFormFieldChild> child = new List<DBFormFieldChild>();
}
public class DBFormFieldOption
{
public List<DBFormFieldGrid> grid_rows = new List<DBFormFieldGrid>();
public List<DBFormFieldGrid> grid_columns = new List<DBFormFieldGrid>();
public string label1 { get; set; }
public string label2 { get; set; }
public string result_label { get; set; }
public string operation { get; set; }
public List<string> rows = new List<string>();
public string tab_id { get; set; }
}
public class DBFormFieldChild
{
public string type { get; set; }
public string label { get; set; }
public string order { get; set; }
}
public class DBFormFieldGrid
{
public string title { get; set; }
public string name { get; set; }
}
I have tried a few strategies to do this. The latest, I was trying this http://james.newtonking.com/json/help/CustomCreationConverter
For example:
List<DBFormField> parsedFields = new List<DBFormField>();
parsedFields = JsonConvert.DeserializeObject<List<DBFormField>>(someFormObj.form_fields.ToString, new FormConverter()); // ToString???
...
Public Class FormConverter
Inherits Converters.CustomCreationConverter(Of DBFormField)
Public Overrides Function Create(objectType As Type) As DBFormField
Return New DBFormField()
End Function
End Class
I suspect putting .ToString on the end of the JObject is not good enough for the DeserializeObject method? See comment above. But this code throws the error...
Cannot deserialize the current JSON object (e.g. {"name":"value"})
into type 'System.Collections.Generic.List`1[RSAP.DBFormField]'
because the type requires a JSON array (e.g. [1,2,3]) to deserialize
correctly.
I haven't tried serialising the JObject to a JSON string- this seems daft considering we have already parsed the JSON into a Jobject.
You've got single object in json and you try to deserialize it to list of objects - that can not be done.
Solutions:
You can wrap json object in array by adding [ and ] around object
You can deserialize to single object (not list):
JsonConvert.DeserializeObject<DBFormField>(someFormObj.form_fields.ToString(), new FormConverter());
You can deserialize single object and add it to list:
List<DBFormField> parsedFields = new List<DBFormField>();
parsedField = JsonConvert.DeserializeObject<DBFormField>someFormObj.form_fields.ToString(), new FormConverter());
parsedFields.Add(parsedField);