I am trying to program .net c# code to read the results from a call to campaignEmailStatsAIMAll().
Here is a sample of the JSON results I get:
{
"total":3,
"data":{
"some...#company.com":[
{
"action":"click",
"timestamp":"2012-10-18 20:55:52",
"url":"http:\/\/www.someurl.com?ct=t(First_Chimp_Test10_18_2012)",
"ip":"66.66.666.666"
},
{
"action":"open",
"timestamp":"2012-10-18 20:55:52",
"url":null,
"ip":"66.66.666.666"
}
],
"anothe...#corporation.com":[
{
"action":"open",
"timestamp":"2012-10-18 20:18:05",
"url":null,
"ip":"22.222.222.222"
},
{
"action":"open",
"timestamp":"2012-10-18 20:18:18",
"url":null,
"ip":"22.222.222.222"
},
{
"action":"click",
"timestamp":"2012-10-18 20:18:18",
"url":"http:\/\/www.someurl.com?ct=t(First_Chimp_Test10_18_2012)",
"ip":"22.222.222.222"
},
{
"action":"click",
"timestamp":"2012-10-18 20:21:57",
"url":"http:\/\/www.someurl.com?ct=t(First_Chimp_Test10_18_2012)",
"ip":"22.222.222.222"
}
],
"thir...#business.com":[
]
}
}
The problem I am having is how to define the C# object to accept this JSON string. The email addresses are being treated as the name part of a JSON name/value pair. I know there are 3rd party wrappers for .NET but I only want to call this API (maybe a couple of others down the line) and would prefer to code it myself. I want to be able to iterate through the object to extract the email address then action/timestamp/url for each one.
When I drop this JSON into the object creator at json2sharp.com, I get this:
public class SomebodyCompanyCom {
public string action { get; set; }
public string timestamp { get; set; }
public string url { get; set; }
public string ip { get; set; }
}
public class AnotherpersonCorporationCom {
public string action { get; set; }
public string timestamp { get; set; }
public string url { get; set; }
public string ip { get; set; }
}
public class Data {
public List<SomebodyCompanyCom> __invalid_name__somebody#company.com { get; set; }
public List<AnotherpersonCorporationCom> __invalid_name__anotherperson#corporation.com { get; set; }
public List<object> __invalid_name__thirdguy#business.com { get; set; }
}
public class RootObject {
public int total { get; set; }
public Data data { get; set; }
}
A generator like that can only ever make best-guesses. Since JSON is generally schema-less, you need to analyze the data and figure out the best way to model it.
In your case, you have two basic types:
the individual entries consisting of action, timestamp, url, and ip
the overall container with total and data
A reasonable model might look like this:
public class ItemInfo {
public string action { get; set; }
public string timestamp { get; set; }
public string url { get; set; }
public string ip { get; set; }
}
public class ContainerType {
public int total;
public Dictionary<string, ItemInfo[]> data;
}
If you use a decent JSON library like JSON.Net, you could deserialize the JSON string into an ContatinerType structure like so:
string rawJsonString = MagicallyGetTheJsonFromAWebservice();
ContainerType container = JsonConvert.DeserializeObject<ContainerType>(rawJsonString);
It might need a bit of tweaking to get the type deserialization to work exactly, but that's the basic idea.
Edit: sample console program to do the deserialization:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Newtonsoft.Json;
namespace ConsoleApplication1
{
class Program
{
static string testData = #"{
'total':3,
'data':{
'some...#company.com':[
{
'action':'click',
'timestamp':'2012-10-18 20:55:52',
'url':'http:\/\/www.someurl.com?ct=t(First_Chimp_Test10_18_2012)',
'ip':'66.66.666.666'
},
{
'action':'open',
'timestamp':'2012-10-18 20:55:52',
'url':null,
'ip':'66.66.666.666'
}
],
'anothe...#corporation.com':[
{
'action':'open',
'timestamp':'2012-10-18 20:18:05',
'url':null,
'ip':'22.222.222.222'
},
{
'action':'open',
'timestamp':'2012-10-18 20:18:18',
'url':null,
'ip':'22.222.222.222'
},
{
'action':'click',
'timestamp':'2012-10-18 20:18:18',
'url':'http:\/\/www.someurl.com?ct=t(First_Chimp_Test10_18_2012)',
'ip':'22.222.222.222'
},
{
'action':'click',
'timestamp':'2012-10-18 20:21:57',
'url':'http:\/\/www.someurl.com?ct=t(First_Chimp_Test10_18_2012)',
'ip':'22.222.222.222'
}
],
'thir...#business.com':[
]
}
}";
public class ItemInfo {
public string action { get; set; }
public string timestamp { get; set; }
public string url { get; set; }
public string ip { get; set; }
}
public class ContainerType {
public int total;
public Dictionary<string, ItemInfo[]> data;
}
static void Main(string[] args)
{
ContainerType container = JsonConvert.DeserializeObject<ContainerType>(testData);
if((container.total != 3)
|| (container.data.Count != 3)
|| (container.data["some...#company.com"][1].action != "open")
|| (container.data["anothe...#corporation.com"][2].url != "http://www.someurl.com?ct=t(First_Chimp_Test10_18_2012)"))
{
Console.WriteLine("Failed to deserialize");
}
else
{
Console.WriteLine("Successfully deserialized");
}
foreach (string email in container.data.Keys)
{
Console.WriteLine(email);
for (int x = 0; x < container.data[email].Count(); x++)
{
Console.WriteLine("\t" + x.ToString() + ":");
Console.WriteLine("\t\taction : " + container.data[email][x].action);
Console.WriteLine("\t\ttimestamp: " + container.data[email][x].timestamp);
Console.WriteLine("\t\turl : " + container.data[email][x].url);
Console.WriteLine("\t\tip : " + container.data[email][x].ip);
}
}
}
}
}
Related
I'm running into issues parsing a json reponse from GraphQL. The issue is the array will come back with more arrays half the time. My code is just getting out of hand and ugly.
Json file (trimmed it a bit. It can be 20+ data arrays)
{
"activity_logs": [
{
"data": "{\"board_id\":2165785546,\"group_id\":\"new_group2051\",\"is_top_group\":false,\"pulse_id\":2165787062,\"pulse_name\":\"Tyler\",\"column_id\":\"email_address\",\"column_type\":\"email\",\"column_title\":\"Email Address\",\"value\":{\"column_settings\":{\"includePulseInSubject\":true,\"ccPulse\":true,\"bccList\":\"\"}},\"previous_value\":{\"email\":\"tyler#email.com\",\"text\":\"tyler#email.com\",\"changed_at\":\"2022-02-15T21:18:48.297Z\",\"column_settings\":{\"includePulseInSubject\":true,\"ccPulse\":true,\"bccList\":\"\"}},\"is_column_with_hide_permissions\":false,\"previous_textual_value\":\"tyler#email.com\"}"
},
{
"data": "{\"board_id\":2165785546,\"group_id\":\"new_group2051\",\"is_top_group\":false,\"pulse_id\":216578711,\"pulse_name\":\"Nicholas \",\"column_id\":\"email_address\",\"column_type\":\"email\",\"column_title\":\"Email Address\",\"value\":{\"column_settings\":{\"includePulseInSubject\":true,\"ccPulse\":true,\"bccList\":\"\"}},\"previous_value\":{\"email\":\"nicholas#email.com\",\"text\":\"nicholas#email.com\",\"changed_at\":\"2022-02-16T04:44:52.046Z\",\"column_settings\":{\"includePulseInSubject\":true,\"ccPulse\":true,\"bccList\":\"\"}},\"is_column_with_hide_permissions\":false,\"previous_textual_value\":\"nicholas#email.com\"}"
},
{
"data": "{\"board_id\":2165785546,\"group_id\":\"new_group2051\",\"is_top_group\":false,\"pulse_id\":216578711,\"pulse_name\":\"Nicholas \",\"column_id\":\"batch_5\",\"column_type\":\"text\",\"column_title\":\"Batch #\",\"value\":{\"value\":\"75\"},\"previous_value\":{\"value\":\"74\"},\"is_column_with_hide_permissions\":false}"
},
{
"data": "{\"board_id\":2165785546,\"group_id\":\"new_group2051\",\"pulse_id\":216578711,\"is_top_group\":false,\"value\":{\"name\":\"Nicholas \"},\"previous_value\":{\"name\":\"Nicholas \"},\"column_type\":\"name\",\"column_title\":\"Name\"}"
}
]
}
Random "get it to work" attempt after giving up on making is a List based on a Class. The IContainers within IContainers were getting very complex.
var responseData = JObject.Parse(responseText).SelectToken("data").SelectToken("boards").SelectToken("activity_logs");
dynamic updatedRecords = JsonConvert.DeserializeObject(responseData.ToString());
foreach (var record in updatedRecords)
{
List<Dictionary<string, string>> records = new List<Dictionary<string, string>>();
Dictionary<string, string> fields = new Dictionary<string, string>();
dynamic updates = JsonConvert.DeserializeObject(JObject.Parse(record.ToString()).SelectToken("data").ToString());
foreach(var update in updates)
{
switch (update.Name.ToString())
{
case "column_id":
fields.Add(update.Name.ToString(), update.Value.ToString());
break;
case "pulse_name":
fields.Add(update.Name.ToString(), update.Value.ToString());
break;
case "value":
dynamic values = JsonConvert.DeserializeObject(JObject.Parse(update.Value.ToString()));
if (update.Name.ToString().Contains("column_settings"))
{
foreach (var value in values)
{
dynamic columns = JsonConvert.DeserializeObject(JObject.Parse(value.Value.ToString()));
foreach(var column in columns)
{
fields.Add($"Value_{column.Name.ToString()}", column.Value.ToString());
}
}
}
else
{
foreach (var value in values)
{
fields.Add($"Value_{value.Name.ToString()}", value.Value.ToString());
}
}
break;
case "previous_value":
dynamic prevValues = JsonConvert.DeserializeObject(JObject.Parse(update.Value.ToString()));
foreach (var prevalue in prevValues)
{
fields.Add($"Prevalue_{prevalue.Name.ToString()}", prevalue.Value.ToString());
}
break;
case "previous_textual_value":
fields.Add(update.Name.ToString(), update.Value.ToString());
break;
}
}
if (fields.Count > 0)
{
records.Add(fields);
fields.Clear();
}
}
My Error when I get to:
dynamic values = JsonConvert.DeserializeObject(JObject.Parse(update.Value.ToString()));
- $exception {"The best overloaded method match for 'Newtonsoft.Json.JsonConvert.DeserializeObject(string)' has some invalid arguments"} Microsoft.CSharp.RuntimeBinder.RuntimeBinderException
Solution is a big help and led to my answer. The issue is the activity_logs data comes with escape characters in it so the string contains \\".
I had to format the data sections with Replace("\\", "") and Replace("\"{", "{") and Replace("}\""), "}"). This made the string readable as a Json file.
You have to pass in a string to DeserializeObject instead of a JSON object.
Another way would be get your JSON mapped to a POCO types as follows, easy way to do is on Visual Studio (Copy your JSON contents, on Visual Studio create a new empty class -> Edit-> Past Special -> Paste JSON as classes)
public class LogsRoot
{
public Activity_Logs[] activity_logs { get; set; }
}
public class Activity_Logs
{
public string data { get; set; }
}
public class DataRoot
{
public long board_id { get; set; }
public string group_id { get; set; }
public bool is_top_group { get; set; }
public long pulse_id { get; set; }
public string pulse_name { get; set; }
public string column_id { get; set; }
public string column_type { get; set; }
public string column_title { get; set; }
public Value value { get; set; }
public Previous_Value previous_value { get; set; }
public bool is_column_with_hide_permissions { get; set; }
public string previous_textual_value { get; set; }
}
public class Value
{
public Column_Settings column_settings { get; set; }
}
public class Column_Settings
{
public bool includePulseInSubject { get; set; }
public bool ccPulse { get; set; }
public string bccList { get; set; }
}
public class Previous_Value
{
public string email { get; set; }
public string text { get; set; }
public DateTime changed_at { get; set; }
public Column_Settings1 column_settings { get; set; }
}
public class Column_Settings1
{
public bool includePulseInSubject { get; set; }
public bool ccPulse { get; set; }
public string bccList { get; set; }
}
Then load the JSON and manipulate as follows,
var json = File.ReadAllText("data.json");
var rootLogs = JsonConvert.DeserializeObject<LogsRoot>(json);
Dictionary<string, string> fields = new Dictionary<string, string>();
foreach (var logJson in rootLogs.activity_logs)
{
var log = JsonConvert.DeserializeObject<DataRoot>(logJson.data);
fields.Add(log.column_id, log.value.column_settings.bccList + log.value.column_settings.ccPulse);
fields.Add(log.pulse_name, log.value.column_settings.bccList + log.value.column_settings.ccPulse);
fields.Add(log.previous_value.email, log.value.column_settings.bccList + log.value.column_settings.ccPulse);
fields.Add(log.previous_textual_value, log.value.column_settings.bccList + log.value.column_settings.ccPulse);
}
This might not solve all your issues, but for the specific exception you are running into, it is because you are trying to deserialize a JObject instead of string.
Probably you just want:
dynamic values = JsonConvert.DeserializeObject(update.Value.ToString());
I'm trying to deserialize a json file in c# and print the values of each individual value by using the key, but for the json values that are a list, I'm unable to print the desired values.
Json file:
{
"prod": {
"vpc_name": "vpc-us-east-1-it-prod",
"subnets": {
"application": [ "subnet-1234", "subnet-1345" ],
"data": [ "subnet-64t3", "subnet-f321" ],
"edge": [ "subnet-1ff3", "subnet-134g" ]
}
},
"dev": {
"vpc_name": "vpc-us-east-1-it-dev",
"subnets": {
"application": [
{ "subnet_id": "subnet-2345tf", "az": "us-east-1a" },
{ "subnet_id": "subnet-143f1", "az": "us-east-1b" }
],
"data": [
{ "subnet_id": "subnet-134f", "az": "us-east-1b" },
{ "subnet_id": "subnet-1324", "az": "us-east-1a" }
],
"edge": [
{ "subnet_id": "subnet-123434", "az": "us-east-1a" },
{ "subnet_id": "subnet-123fg", "az": "us-east-1b" }
]
}
}
}
C# code
using System;
using System.Collections.Generic;
using System.IO;
using System.Text.Json;
namespace JsonDeserializer
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello World!");
string jsonString = File.ReadAllText(#"C:/Users/Stephen.Carvalho/source\repos/JsonDeserializer/JsonDeserializer/vpc_stack.json");
Rootobject vpcs = JsonSerializer.Deserialize<Rootobject>(jsonString);
Console.WriteLine(vpcs.dev.vpc_name);
Console.WriteLine(vpcs.dev.subnets.application);
}
}
public class Rootobject
{
public Prod prod { get; set; }
public Dev dev { get; set; }
}
public class Prod
{
public string vpc_name { get; set; }
public Subnets subnets { get; set; }
}
public class Subnets
{
public string[] application { get; set; }
public string[] data { get; set; }
public string[] edge { get; set; }
}
public class Dev
{
public string vpc_name { get; set; }
public Subnets1 subnets { get; set; }
}
public class Subnets1
{
public Application[] application { get; set; }
public Datum[] data { get; set; }
public Edge[] edge { get; set; }
}
public class Application
{
public string subnet_id { get; set; }
public string az0885b3b66d { get; set; }
public string az { get; set; }
}
public class Datum
{
public string subnet_id { get; set; }
public string az { get; set; }
}
public class Edge
{
public string subnet_id { get; set; }
public string az { get; set; }
}
}
Output
Hello World!
vpc-us-east-1-it-dev
JsonDeserializer.Application[]
I want to print the list of application subnets with prod.subnets but instead of getting the values returned I'm getting JsonDeserializer.Application[] as the output
That is because vpcs.dev.subnets.application is an array of Application. You can print the array of application subnets by first getting the subnet_ids then converting that array to a string.
Reason you see JsonDeserializer.Application[] is because your printing the object itself.. when you do that, you get the name of the object type instead of the values inside of it.
Console.WriteLine(string.Join(", ", vpcs.dev.subnets.application.Select(x => x.subnet_id)));
The Select statment goes through each of the application and returns only the subnet_id. Whenever you have an array / list, you can use the select method to get specific items from the list or create new object with this as well.
Documentation on Select
That's happening since you're trying to print an array in an line, you can try doing something like this:
Array.ForEach(vpcs.dev.subnets.application, Console.WriteLine);
or parsing it to a list and printing it
vpcs.dev.subnets.application.ToList().ForEach(i => Console.WriteLine(i.ToString()));
or you can also try doing it in a foreach:
foreach(var item in vpcs.dev.subnets.application)
{
Console.WriteLine(item.ToString());
}
anyone know how to insert this json array into mongodb using insertmany() and C# ??
i cant find any good source for this problem
MongoCollectionBase.InsertMany expects an IEnumerable<TDocument>.
So you need to deserialize your data json element to TDocument[], (Datum) and then pass that array to InsertMany.
Based on the below json, which is different from your screenshot
{
"data": [
{
"pulsa_code": "alfamart100",
"pulsa_op": "Alfamart Voucher",
"pulsa_nominal": "Voucher Alfamart Rp 100.000",
"pulsa_price": 100000,
"pulsa_type": "voucher",
"masaaktif": "0",
"status": "active"
}
]
}
This should work
//...
public class Datum
{
public string pulsa_code { get; set; }
public string pulsa_op { get; set; }
public string pulsa_nominal { get; set; }
public double pulsa_price { get; set; }
public string pulsa_type { get; set; }
public string masaaktif { get; set; }
public string status { get; set; }
public double harga { get; set; }
}
public class PriceListPrepaidModel
{
public List<Datum> data { get; set; }
}
public class PriceList : BaseDatabase
{
//NOTE: The strongly typed IMongoCollection<T> must be the same type as the entities passed to InsertMany
private IMongoCollection<Datum> _pricelistCollection;
//private IMongoCollection<PriceListPrepaidModel> _pricelistCollection;
public PriceList(IServiceProvider serviceProvider)
{
_pricelistCollection = DB.GetCollection<PriceListPrepaidModel>("price_prepaid");
}
public ResponseModel<string> PriceListPrepaidTest(PriceListPrepaidRequest request)
{
var entityResult = new ResponseModel<string>();
try
{
Console.WriteLine(response.Content);
//Desirialize to your model class, not JObject
var model = JsonConvert.DeserializeObject<PriceListPrepaidModel>(message.AsString);
foreach (var item in model.data)
{
item.pulsa_price = (int)item.pulsa_price + 200;
}
//Insert the array of `Datum`
_pricelistCollection.InsertMany(model.data);
entityResult.Value = JsonConvert.SerializeObject(model.data);
entityResult.Status = true;
}
catch (Exception ex)
{
entityResult.Messages.Add(new ResponseMessageModel()
{
Type = ResponseMessageModel.MessageType.ERROR,
Title = "Error",
Message = ex.Message
});
}
return entityResult;
}
}
I have a json as deined below ,
{
"ApplicationOne": {
"Version": "1.0",
"Owner": "coderClan"
},
"ApplicationTwo": {
"Version": "2.0",
"Owner": "gamers"
}
}
I am trying to implement a method such that when an application ID (ApplicationOne , ApplicationTwo) is passed as a parameter , the owner will be returned
public static string GetOwner(string applicationID)
{
string owner = ""; //Deserialized Owner Name
return owner;
}
The problem I have is that I have no way of being certain of the application ID as that can be changed ? hence I cannot create the POCO classes as below,
public class ApplicationOne
{
public string Version { get; set; }
public string Owner { get; set; }
}
public class ApplicationTwo
{
public string Version { get; set; }
public string Owner { get; set; }
}
public class RootObject
{
public ApplicationOne ApplicationOne { get; set; }
public ApplicationTwo ApplicationTwo { get; set; }
}
Is it still possible to deserialize this ? Would really appreciate an example of how I can implement this
You can do this with Newtonsoft.Json using dynamic:
dynamic deserialized = JsonConvert.DeserializeObject(json);
var result = deserialized["ApplicationOne"]?.Owner?.ToObject<string>();
And the method:
public static string GetOwner(string applicationID)
{
return deserialized[applicationID]?.Owner?.ToObject<string>();
}
Im having with the content. it is auto increment.
the result is static but the content is dynamic.
I'm using a hardcoded array in catching the return string from the web. Can anyone json decoder in converting the returned string to c# object
This is the returned string from web:
{
"result":{
"count":"3"
},
"content_1":{
"message_id":"23",
"originator":"09973206870",
"message":"Hello",
"timestamp":"2016-09-14 13:59:47"
},
"content_2":{
"message_id":"24",
"originator":"09973206870",
"message":"Test again.",
"timestamp":"2016-09-14 14:49:14"
},
"content_3":{
"message_id":"25",
"originator":"09973206870",
"message":"Another message",
"timestamp":"2016-09-14 14:49:20"
}
}
On site json2csharp.com you can generate classes for JSON data.
Generated classes needs some improvements and can look like:
public class Result
{
public string count { get; set; }
}
public class Content
{
public string message_id { get; set; }
public string originator { get; set; }
public string message { get; set; }
public string timestamp { get; set; }
}
public class RootObject
{
public Result result { get; set; }
public Content content_1 { get; set; }
public Content content_2 { get; set; }
public Content content_3 { get; set; }
}
And using JSON.NET you can deserialize it:
public class Program
{
static public void Main()
{
string json = "{ \"result\":{ \"count\":\"3\" }, \"content_1\":{ \"message_id\":\"23\", \"originator\":\"09973206870\", \"message\":\"Hello\", \"timestamp\":\"2016-09-14 13:59:47\" }, \"content_2\":{ \"message_id\":\"24\", \"originator\":\"09973206870\", \"message\":\"Test again.\", \"timestamp\":\"2016-09-14 14:49:14\" }, \"content_3\":{ \"message_id\":\"25\", \"originator\":\"09973206870\", \"message\":\"Another message\", \"timestamp\":\"2016-09-14 14:49:20\" } }";
RootObject ro = JsonConvert.DeserializeObject<RootObject>(json);
Console.WriteLine(ro.content_1.message_id);
Console.WriteLine(ro.content_2.message_id);
}
}