This is the class Database:
namespace vVvBot.Model
{
public class Database
{
public List<CustomCommand> CustomCommands { get; set; }
public List<CustomEvent> CustomEvents { get; set; }
}
}
This is the class for CustomEvent:
namespace vVvBot.Model
{
public class CustomEvent
{
public string Name { get; set; }
public bool Enabled { get; set; }
public List<CustomCommand> Commands { get; set; }
}
}
This is the class CustomCommand:
namespace vVvBot.Model
{
public class CustomCommand
{
public string Keyword { get; set; }
public CommandType Type { get; set; }
public string Message { get; set; }
public bool Enabled { get; set; }
}
}
This is the class where I deserialize and serialize the Database object
namespace vVvBot.Data
{
public class FileJsonContext
{
public Database ReadToObject(string fileName)
{
dynamic jsonData = File.ReadAllText(fileName);
return JsonConvert.DeserializeObject<Database>(jsonData) ?? new Database();
}
public void ObjectToFile(string fileName, Database database)
{
dynamic jsonData = JsonConvert.SerializeObject(database, Formatting.Indented);
File.WriteAllText(fileName, jsonData);
}
}
}
In the file with the issue, this is where I instantiate Database:
private Database _database;
public Database Database => _database ?? (_database = JsonContext.ReadToObject("Commands.txt"));
The line with the issue is:
var messageindex = Database.CustomEvents[index].Commands.FindLastIndex(x => x.Type == CommandType.Welcome);
It tries to complete the line but immediately returns because its comes back with null. There is a List in the custom events that should call the customcommand list so I can access the object. Not sure why it comes back to NULL.
The Json File includes:
{
"CustomCommands": [
{
"Keyword": "Hello",
"Type": 0,
"Message": "World",
"Enabled": true
},
{
"Keyword": "Test",
"Type": 0,
"Message": "test",
"Enabled": true
},
{
"Keyword": "greeting",
"Type": 3,
"Message": "this isnt a test ",
"Enabled": true
},
{
"Keyword": "leaving",
"Type": 4,
"Message": "Sorry to see you go ",
"Enabled": true
},
{
"Keyword": "faq",
"Type": 1,
"Message": "This is a FAQ TEST ",
"Enabled": true
},
{
"Keyword": "Hi",
"Type": 0,
"Message": "Hilo ",
"Enabled": false
},
{
"Keyword": "Hi",
"Type": 0,
"Message": "Hilo ",
"Enabled": false
}
],
"CustomEvents": [
{
"Name": "greeting",
"Enabled": true
},
{
"Name": "leaving",
"Enabled": true
}
]
}
i had this problem a long time ago and i thought the problem was from Unicode.
so i wrote a function for this . you can use it :
List<T> ToJson<T>(byte[] byteArray) where T : new()
{
MemoryStream stream = new MemoryStream(byteArray);
JsonSerializer se = new JsonSerializer();
StreamReader re = new StreamReader(stream);
JsonTextReader reader = new JsonTextReader(re);
return se.Deserialize<List<T>>(reader);
}
and i use this function Like this:
ToJson(data.ToArray());
data is a MemoryStream.
Related
I'm trying to write my own small API. I found an article on how to implement an API with Mongodb on ASP.NET Core MVC: article. The problem is that when creating a GET request, the object is incorrectly serialized. As I understand it, the standard Json serializer cannot serialize objects of a custom data type.
Here is the file with the model that I am reading from the database. Everything comes from the database correctly, but when I try to send a response, a file with an empty List<Weekday> arrives.
[Serializable]
public class Group
{
[BsonId]
[BsonRepresentation(BsonType.ObjectId)]
public string? Id { get; set; }
public string groupName { get; set; }
public Schedule schedule { get; set; }
public Group()
{
groupName = "UNKNOWN";
schedule = new Schedule();
}
public Group(string groupName)
{
this.groupName = groupName;
schedule = new Schedule();
}
}
[Serializable]
public class Schedule
{
public List<Weekday> week = new List<Weekday>();
}
[Serializable]
public class Weekday
{
public List<DaysSchedule> daysSchedules { get; set; } = new List<DaysSchedule>();
public int dayNumber { get; set; } = 0;
}
public class DaysSchedule
{
public List<string> dates = new List<string>();
public List<Classes> classes = new List<Classes>();
}
public class Classes
{
[BsonElement("ordinal")]
public int ordinal { get; set; }
[BsonElement("name")]
public string name { get; set; }
[BsonElement("teacher")]
public string? teacher { get; set; }
[BsonElement("type")]
public string type { get; set; }
[BsonElement("location")]
public string location { get; set; }
public Classes()
{
ordinal = 0;
name = "UNKNOWN";
type = "UNDEFINED";
location = "UNDEFINED";
}
public Classes(int ordinal, string name, string teacher, string type, string location)
{
this.ordinal = ordinal;
this.name = name;
this.teacher = teacher;
this.type = type;
this.location = location;
}
}
Here is an example of a Json file that I expect. I did not insert the entire file, as it is very large. But the main point is that the Week list contains days of the week, each of which has certain schedule options.
{
"Id": "63ea85829903ec2ab03720d3",
"groupName": "М3О-225Бк-21",
"schedule": {
"week": [
{
"daysSchedules": [
{
"dates": [
"13.02.2023",
"13.02.2023"
],
"classes": [
{
"ordinal": 0,
"name": "Math",
"teacher": "Lyahner",
"type": "PZ",
"location": "64"
},
{
"ordinal": 1,
"name": "Programming",
"teacher": "Lyahner",
"type": "LK",
"location": "84"
},
{
"ordinal": 2,
"name": "OOP",
"teacher": "Lyahner",
"type": "LK",
"location": "29"
},
{
"ordinal": 3,
"name": "OOP",
"teacher": "Vestyak",
"type": "LK",
"location": "33"
}
]
},
{
"dates": [
"13.02.2023",
"13.02.2023"
],
"classes": [
{
"ordinal": 0,
"name": "Phisics",
"teacher": "Lyahner",
"type": "LK",
"location": "97"
},
{
"ordinal": 1,
"name": "Programming",
"teacher": "Lyahner",
"type": "LK",
"location": "78"
},
{
"ordinal": 2,
"name": "Programming",
"teacher": "Sukhno",
"type": "PZ",
"location": "91"
},
{
"ordinal": 3,
"name": "Programming",
"teacher": "Sukhno",
"type": "PZ",
"location": "32"
}
]
},
{
"dates": [
"13.02.2023",
"13.02.2023"
],
"classes": [
{
"ordinal": 0,
"name": "OOP",
"teacher": "Vestyak",
"type": "LK",
"location": "93"
},
{
"ordinal": 1,
"name": "Math",
"teacher": "Lyahner",
"type": "PZ",
"location": "72"
},
{
"ordinal": 2,
"name": "Math",
"teacher": "Vestyak",
"type": "LK",
"location": "70"
},
{
"ordinal": 3,
"name": "Phisics",
"teacher": "Vestyak",
"type": "LK",
"location": "42"
}
]
}
],
"dayNumber": 0
.......................................
Here's what Json I get:
{
"id": "63ea85829903ec2ab03720d3",
"groupName": "М3О-225Бк-21",
"schedule": {}
}
Here is the code of my Controller. Here I don't quite understand how the Http Get and Http Post attributes work. I understand that they configure routing and transfer control to a method for processing and sending a response. But where does the serialization of the Group object take place and how is it passed to the method? I tried to implement serialization explicitly by taking a string variable in the Get method and serializing the object using Newtonsoft.Json, it worked, but I don't think this option is correct and suits me. I would like to know what the problem is? And can I set custom serialization for the Group object so that I can pass and return it from methods with routing attributes?
using Newtonsoft.Json;
using Microsoft.AspNetCore.Mvc;
using ThreeplyWebApi.Services;
using ThreeplyWebApi.Models;
using System.Text.Json;
namespace ThreeplyWebApi.Controllers
{
[ApiController]
[Route("controller")]
public class GroupsController : ControllerBase
{
readonly private GroupsService _groupsService;
public GroupsController(GroupsService schedulesService)
{
_groupsService = schedulesService;
}
[HttpGet]
public async Task<List<Group>> Get() => await _groupsService.GetAsync();
[HttpGet("{groupName}")]
public async Task<ActionResult<Group>> Get(string groupName)
{
var group = await _groupsService.GetAsync(groupName);
if (group == null)
{
return NotFound();
}
return Ok(group);
}
[HttpPost]
public async Task<IActionResult> Post([FromBody]Group newGroup)
{
await _groupsService.CreateAsync(newGroup);
return CreatedAtAction(nameof(Get), new { groupName = newGroup.groupName }, newGroup);
}
}
}
I also provide the code of my service for accessing the database, the methods of which are called by the controller to access the database.
namespace ThreeplyWebApi.Services
{
public class GroupsService
{
private readonly IMongoCollection<Group> _groupsCollection;
public GroupsService(IOptions<GroupsDatabaseSettings> groupDatabaseSettings)
{
var MongoClient = new MongoClient(groupDatabaseSettings.Value.ConnectionString);
var MongoDatabase = MongoClient.GetDatabase(groupDatabaseSettings.Value.DatabaseName);
_groupsCollection = MongoDatabase.GetCollection<Group>(groupDatabaseSettings.Value.GroupsCollectionName);
}
public async Task<List<Group>> GetAsync()
{
return await _groupsCollection.Find<Group>(_ => true).ToListAsync();
}
public async Task<Group> GetAsync(string groupName)
{
return await _groupsCollection.Find(x => x.groupName == groupName).FirstOrDefaultAsync();
}
public async Task CreateAsync(Group group) {
await _groupsCollection.InsertOneAsync(group);
}
public async Task UpdateAsync(string groupName, Group updatedGroup) =>
await _groupsCollection.ReplaceOneAsync(x => x.groupName == groupName, updatedGroup);
public async Task RemoveAsync(string groupName) =>
await _groupsCollection.DeleteOneAsync(x => x.groupName == groupName);
}
}
I am having trouble deserializing JSON received from HubSpot ContactList API.
I am using Restsharp and NewtonSoft, and I'm having real struggles understanding how to correctly define the required classes in order to deserialize the JSON string, which is below:
"contacts": [
{
"vid": 2251,
"portal-id": 5532227,
"is-contact": true,
"profile-url": "https://app.hubspot.com/contacts/5532227/contact/2251",
"properties": {
"firstname": {
"value": "Carl"
},
"lastmodifieddate": {
"value": "1554898386040"
},
"company": {
"value": "Cygnus Project"
},
"lastname": {
"value": "Swann"
}
},
"form-submissions": [],
"identity-profiles": [
{
"vid": 2251,
"saved-at-timestamp": 1553635648634,
"deleted-changed-timestamp": 0,
"identities": [
{
"type": "EMAIL",
"value": "cswann#cygnus.co.uk",
"timestamp": 1553635648591,
"is-primary": true
},
{
"type": "LEAD_GUID",
"value": "e2345",
"timestamp": 1553635648630
}
]
}
],
"merge-audits": []
},
{
"vid": 2301,
"portal-id": 5532227,
"is-contact": true,
"profile-url": "https://app.hubspot.com/contacts/5532227/contact/2301",
"properties": {
"firstname": {
"value": "Carlos"
},
"lastmodifieddate": {
"value": "1554886333954"
},
"company": {
"value": "Khaos Control"
},
"lastname": {
"value": "Swannington"
}
},
"identity-profiles": [
{
"vid": 2301,
"saved-at-timestamp": 1553635648733,
"deleted-changed-timestamp": 0,
"identities": [
{
"type": "EMAIL",
"value": "cswann#khaoscontrol.com",
"timestamp": 1553635648578,
"is-primary": true
},
{
"type": "LEAD_GUID",
"value": "c7f403ba",
"timestamp": 1553635648729
}
]
}
],
"merge-audits": []
}
],
"has-more": false,
"vid-offset": 2401
}
If I simply request the vid, I correctly get 2 vid's back. It's when I try to do the properties and that i get a fail.
Please help
Lets reduce the Json to the minimum to reproduce your error :
{
"vid": 2301,
"portal-id": 5532227,
"is-contact": true,
"profile-url": "https://app.hubspot.com/contacts/5532227/contact/2301",
"properties": {
"firstname": {
"value": "Carlos"
},
"lastmodifieddate": {
"value": "1554886333954"
},
"company": {
"value": "Khaos Control"
},
"lastname": {
"value": "Swannington"
}
}
}
And the appropriate class ContactListAPI_Result:
public partial class ContactListAPI_Result
{
[JsonProperty("vid")]
public long Vid { get; set; }
[JsonProperty("portal-id")]
public long PortalId { get; set; }
[JsonProperty("is-contact")]
public bool IsContact { get; set; }
[JsonProperty("profile-url")]
public Uri ProfileUrl { get; set; }
[JsonProperty("properties")]
public Dictionary<string, Dictionary<string, string>> Properties { get; set; }
}
public partial class ContactListAPI_Result
{
public static ContactListAPI_Result FromJson(string json)
=> JsonConvert.DeserializeObject<ContactListAPI_Result>(json);
//public static ContactListAPI_Result FromJson(string json)
// => JsonConvert.DeserializeObject<ContactListAPI_Result>(json, Converter.Settings);
}
public static void toto()
{
string input = #" {
""vid"": 2301,
""portal-id"": 5532227,
""is-contact"": true,
""profile-url"": ""https://app.hubspot.com/contacts/5532227/contact/2301"",
""properties"": {
""firstname"": {
""value"": ""Carlos""
},
""lastmodifieddate"": {
""value"": ""1554886333954""
},
""company"": {
""value"": ""Khaos Control""
},
""lastname"": {
""value"": ""Swannington""
}
}
}";
var foo = ContactListAPI_Result.FromJson(input);
}
But the Value of one property will be burrow in the sub dictionary, we can the project the object in a more usefull one :
public partial class ItemDTO
{
public long Vid { get; set; }
public long PortalId { get; set; }
public bool IsContact { get; set; }
public Uri ProfileUrl { get; set; }
public Dictionary<string, string> Properties { get; set; }
}
Adding the projection to the Class:
public ItemDTO ToDTO()
{
return new ItemDTO
{
Vid = Vid,
PortalId = PortalId,
IsContact = IsContact,
ProfileUrl = ProfileUrl,
Properties =
Properties.ToDictionary(
p => p.Key,
p => p.Value["value"]
)
};
}
Usage :
var result = foo.ToDTO();
Live Demo
Creating and managing class structure for big and nested key/value pair json is tedious task
So one approach is to use JToken instead.
You can simply parse your JSON to JToken and by querying parsed object, you will easily read the data that you want without creating class structure for your json
From your post it seems you need to retrieve vid and properties from your json so try below code,
string json = "Your json here";
JToken jToken = JToken.Parse(json);
var result = jToken["contacts"].ToObject<JArray>()
.Select(x => new
{
vid = Convert.ToInt32(x["vid"]),
properties = x["properties"].ToObject<Dictionary<string, JToken>>()
.Select(y => new
{
Key = y.Key,
Value = y.Value["value"].ToString()
}).ToList()
}).ToList();
//-----------Print the result to console------------
foreach (var item in result)
{
Console.WriteLine(item.vid);
foreach (var prop in item.properties)
{
Console.WriteLine(prop.Key + " - " + prop.Value);
}
Console.WriteLine();
}
Output:
"fields": [
{
"field": {
"name": "SMS",
"value": "Yes"
}
},
{
"field": {
"name": "Email",
"value": ""
}
},
{
"field": {
"name": "Total",
"value": ""
}
},
]
I have tried to form the JSON format like above, so i formed the class like below. While serialization it does not return expected form, how can i achieve this one.
public class Test
{
public List<Field> fields;
}
public class Field
{
public string name { get; set; }
public string value { get; set; }
}
Response:
"fields": [{
"name": "SMS",
"value": "Yes"
}, {
"name": "Email",
"value": ""
},{
"name": "Total",
"value": ""
}]
Use this website http://json2csharp.com and generate all the classes automatically. Just copy-paste your json there.
You can customize resulting JSON object with anonymous types and LINQ. Please try this code:
var test = new Test {fields = new List<Field>()};
test.fields.Add(new Field {name = "f1", value = "v1"});
test.fields.Add(new Field {name = "f2", value = "v2"});
var json = JObject.FromObject(new { fields = test.fields.Select(f => new {field = f}).ToArray() })
.ToString();
A json variable would be:
{
"fields": [
{
"field": {
"name": "f1",
"value": "v1"
}
},
{
"field": {
"name": "f2",
"value": "v2"
}
}
]
}
You just missed a class level:
public class Test
{
public List<FieldHolder> fields;
}
public class FieldHolder
{
public Field field { get; set; }
}
public class Field
{
public string name { get; set; }
public string value { get; set; }
}
I am writing tests for my controllers (ASP.NET Core), and am receiving back some JSON. I would now like to deserialize it into the correct object so that I can do some assertions against the returned data. There are no exceptions thrown during deserialization, but my Data variable is null.
Here is the code used for the deserialization:
var output = JsonConvert.DeserializeObject(responseString,
typeof(CrudOperationResult<IEnumerable<ApiResource>>));
This is the CrudOperationResult class:
public class CrudOperationResult<T>
{
private CrudOperationResult()
{ }
private CrudOperationResult(CrudResult result, string errorMessage, T data)
{
Result = result;
ErrorMessage = errorMessage;
Data = data;
}
[JsonIgnore]
public CrudResult Result { get; private set; }
public bool IsError
{
get
{
return Result == CrudResult.Error;
}
}
public string ErrorMessage { get; private set; }
public T Data { get; private set; }
}
And here is the JSON data returned:
{
"isError": false,
"errorMessage": null,
"data": [{
"id": 1,
"enabled": true,
"name": "apiResource1",
"displayName": "My API",
"description": null,
"secrets": null,
"scopes": [{
"id": 1,
"name": "apiResource1",
"displayName": "My API",
"description": null,
"required": false,
"emphasize": false,
"showInDiscoveryDocument": true,
"userClaims": null
}],
"userClaims": [{
"id": 1,
"type": "role"
},
{
"id": 2,
"type": "user"
}]
}]
}
Because of the [...] JsonConvert.DeserializeObject thinks data a List<T> Data { get; private set; }.
Issue 1: To deserialize JSON, you need a public constructor with no arguments.
Issue 2: You can't deserialize an interface type (IEnumerable).
Try:
var output = JsonConvert.DeserializeObject(responseString,
typeof(CrudOperationResult<List<ApiResource>>));
use this function :
List<T> ToJson<T>(byte[] byteArray) where T : new()
{
MemoryStream stream = new MemoryStream(byteArray);
JsonSerializer se = new JsonSerializer();
StreamReader re = new StreamReader(stream);
JsonTextReader reader = new JsonTextReader(re);
return se.Deserialize<List<T>>(reader);
}
I'm currently trying to read Json file (named initial_data.json) which reside in the folder DataModels in my Project folder. The problem I'm having is it won't read the file. I have tried the following code to read the file to json string (which I will use it to deserialize later, so I've tried to display it into resultTextBlock) and nothing has came out.
Here's my Json file format
{
"brands": [
{
"id": "AUD",
"name": "AUDI",
"sort": "99",
"active": true
},
{
"id": "BEN",
"name": "MERCEDES-BENZ",
"sort": "6",
"active": true
},
{
"id": "BMW",
"name": "BMW",
"sort": "7",
"active": true
},
{
"id": "CHE",
"name": "CHEVROLET",
"sort": "8",
"active": true
}
],
"models": [
{
"id": "100",
"name": "CIVIC",
"brandID": "HON",
"size": null,
"year": "-",
"active": true
},
{
"id": "101",
"name": "CRV",
"brandID": "HON",
"size": null,
"year": "-",
"active": true
},
{
"id": "102",
"name": "CRVEXI",
"brandID": "HON",
"size": null,
"year": "-",
"active": true
},
{
"id": "103",
"name": "GDYSSEY",
"brandID": "HON",
"size": null,
"year": "-",
"active": true
}
]
}
Here's my json Class
public class Brand
{
[JsonProperty("id")]
public string id { get; set; }
[JsonProperty("name")]
public string name { get; set; }
[JsonProperty("sort")]
public string sort { get; set; }
[JsonProperty("active")]
public bool active { get; set; }
[JsonProperty("path")]
public string path { get; set; }
}
public class Model
{
[JsonProperty("id")]
public string id { get; set; }
[JsonProperty("name")]
public string name { get; set; }
[JsonProperty("brandID")]
public string brandID { get; set; }
[JsonProperty("size")]
public object size { get; set; }
[JsonProperty("year")]
public string year { get; set; }
[JsonProperty("active")]
public bool active { get; set; }
}
And here's how I write my reading function
private async Task readJsonAsync()
{
// Notice that the write **IS** identical ... except for the serializer.
string content = String.Empty;
var myStream = await ApplicationData.Current.LocalFolder.OpenStreamForReadAsync(JSONFILENAME);
using (StreamReader reader = new StreamReader(myStream))
{
content = await reader.ReadToEndAsync();
}
resultTextBlock.Text = content;
}
Any help would be appreciated
think there might be some issue with the path you specified for the file name.
Please put your file in assets folder and follow the below code
var fileStream = File.OpenRead("Assets/" + "sampleJson.txt");//You can specify your file name here.
using (StreamReader reader = new StreamReader(fileStream))
{
var content = await reader.ReadToEndAsync();
}