Is it possible to skip object name during Json Serialization? - c#

I have the below properties of an object:
public string SenderAccount { get; set; }
public string ReceiverAccount { get; set; }
public decimal Amount { get; set; }
public string Currency { get; set; }
public Info Info { get; set; }
And I want to have an output like this:
{ "sender_account":"1753154",
"receiver_account":"1753242",
"amount":15,
"currency":"USD",
"test":1,
"key":"_MERCHANT_KEY_",
"ts":_TIMESTAMP_,
"sign":"_SIGN_"
}
Where test,key,ts and sign, belong to Info object.
Now I want to skip this part:
1."Info":
2.{
3. "test":0,
4. "key":"mkey",
5. "ts":time_stamp,
6. "sign":"signature"
7.}
But to output only Info variables.
Reason is that from api documentation provided they use all time those Info variables to request.
Edit: I need to skip rows 1,2,7 during serialization.

You can do it like:
Object1 object1 = new Object1
{
sender_account = "1753154",
receiver_account = "1753242",
amount = 15,
currency = "USD",
Info = new Info
{
test = 1,
key = "_MERCHANT_KEY_",
ts = "_TIMESTAMP_",
sign = "_SIGN_"
}
};
And serialize it like:
var resultJson = JsonConvert.SerializeObject(new
{
object1.sender_account,
object1.receiver_account,
object1.amount,
object1.currency,
object1.Info.test,
object1.Info.key,
object1.Info.ts,
object1.Info.sign,
});
Output:
{
"sender_account": "1753154",
"receiver_account": "1753242",
"amount": 15,
"currency": "USD",
"test": 1,
"key": "_MERCHANT_KEY_",
"ts": "_TIMESTAMP_",
"sign": "_SIGN_"
}

Related

Working with Irregular nodes/elements in json response from an API

I have a situation while working with a JSON response from an API. To give a background, I am consuming an API from a source using a REST API using 3.5 .net framework.
Below is the part of the JSON output and I am kind of struggling to use it.
a)
"value": {
"Description": "Total Calculated things",
"2018": "5,820,456 ",
"2019": "2,957,447 "
}
The last 2 elements are dynamic, those are tend to change in API response. I was expecting the format like I have mentioned below, but at this point of given time the source provider is not able to change it as the API is used in many other different programs. And Changing the things in the source API will make other program owners to change.
b)
"value": {
"Description": "Total Calculated EQUITY AND LIABILITIES",
"YearData": [ {
"Data": "5,820,456",
"Year": "2018"
},
{
"Data": "2,957,447 ",
"Year": "2019"
} ]
}
Is there any way to overcome such thing> Any way to convert a to b?
EDIT
#Xerillio , Thanks . How can I achieve the same using below JSON format.
var json = #"
{
""entityData"": [
{
""name"": ""Statement of Comprehensive Income"",
""subattrOutput"": [
{
""name"": ""Sales"",
""subattrOutput"": [],
""value"": {
""Description"": ""Sales "",
""2018"": ""8,704,888 "",
""2019"": ""4,760,717 ""
},
""score"": ""99.5"",
""valuetype"": ""object""
},
{
""name"": ""Cost of goods sold"",
""subattrOutput"": [],
""value"": {
""Description"": ""Cost of sales "",
""2018"": ""(6,791,489) "",
""2019"": ""(3,502,785) ""
},
""score"": ""99.75"",
""valuetype"": ""object""
}
],
""value"": null,
""score"": ""98.63"",
""valuetype"": ""object""
}
]
}";
I wish this was more easy, but i just got it here:
class Program
{
static async Task Main(string[] args)
{
string json1 = #"{""value"": {""Description"": ""Total Calculated things"",""2018"": ""5,820,456 "",""2019"": ""2,957,447 ""}}";
string json2 = #"{""value"": {""Description"": ""Total Calculated EQUITY AND LIABILITIES"",""YearData"": [ {""Data"": ""5,820,456"",""Year"": ""2018""},{""Data"": ""2,957,447 "",""Year"": ""2019""} ]}}";
var obj1 = JsonConvert.DeserializeObject<ObjectResult>(json1);
var obj2 = JsonConvert.DeserializeObject<ObjectResult>(json2);
var res1 = CastObject<Result1>(obj1.Value.ToString());
var res2 = CastObject<Result2>(obj2.Value.ToString());
var invalidRes1 = CastObject<Result1>(obj2.Value.ToString());
var invalidRes2 = CastObject<Result2>(obj1.Value.ToString());
Console.WriteLine(res1);
Console.WriteLine(res2);
}
public static T CastObject<T>(string obj)
{
return !TryCastObject(obj, out T result) ? default : result;
}
public static bool TryCastObject<TOut>(string objToCast, out TOut obj)
{
try
{
obj = JsonConvert.DeserializeObject<TOut>(objToCast);
return true;
}
catch
{
obj = default;
return false;
}
}
}
public class ObjectResult
{
public object Value { get; set; }
}
public class Result1
{
[JsonProperty(PropertyName = "description")] public string Description { get; set; }
[JsonProperty(PropertyName = "2018")] public string _2018 { get; set; }
[JsonProperty(PropertyName = "2019")] public string _2019 { get; set; }
}
public class Result2
{
[JsonProperty(PropertyName = "Description")] public string Description { get; set; }
[JsonProperty(PropertyName = "YearData")] public List<YearData> YearData { get; set; }
}
public class YearData
{
[JsonProperty(PropertyName = "Data")] public string Data { get; set; }
[JsonProperty(PropertyName = "Year")] public string Year { get; set; }
}
It is A LOT of work and sincerely, as there more nodes in the json i think that using JObject is the best option, and you will have to do a deserealization in more than 1 step :(
Depending on how large the JSON structure is you could deserialize it into a Dictionary and manually map it to the proper format:
var json = #"
{
""value"": {
""Description"": ""Total Calculated things"",
""2018"": ""5,820,456 "",
""2019"": ""2,957,447 ""
}
}";
var badObj = JsonSerializer.Deserialize<BadFormat>(json);
var result = new WrapperType
{
Value = new ProperlyFormattedType()
};
foreach (var pair in badObj.Value)
{
if (pair.Key == "Description")
{
result.Value.Description = pair.Value;
}
else if (int.TryParse(pair.Key, out int _))
{
result.Value.YearData
.Add(new DatedValues
{
Year = pair.Key,
Data = pair.Value
});
}
}
// Data models...
public class BadFormat
{
[JsonPropertyName("value")]
public Dictionary<string, string> Value { get; set; }
}
public class WrapperType
{
public ProperlyFormattedType Value { get; set; }
}
public class ProperlyFormattedType
{
public string Description { get; set; }
public List<DatedValues> YearData { get; set; } = new List<DatedValues>();
}
public class DatedValues
{
public string Year { get; set; }
public string Data { get; set; }
}
See an example fiddle here.

Keep application-specific fields synced with database

I have a GameConsole model :
public class GameConsole
{
public int ID { get; protected set; } = 0;
public string Identifier { get; protected set; } = "GameConsole";
public List<string> ValidInputs { get; set; } = new List<string>(8);
public Dictionary<string, InputAxis> InputAxesMap { get; protected set; } = new Dictionary<string, InputAxis>(8);
public Dictionary<string, InputButton> InputButtonMap { get; protected set; } = new Dictionary<string, InputButton>(32);
public string ValidInputsStr { get; set; } = string.Empty;
public string InputAxesMapStr { get; set; } = string.Empty;
public string InputButtonMapStr { get; set; } = string.Empty;
}
I need ValidInputs, InputAxesMap, and InputButtonMap stored in an SQLite database. I've done this by serializing to JSON in their respective ValidInputsStr, InputAxesMapStr, and InputButtonMapStr fields.
However, I need to use these lists and dictionaries in the application. But each time I open the database context, ValidInputs, InputAxesMap, and InputButtonMap don't contain the data (unless I deserialize them from the JSON strings).
using (MyDatabaseContext context = new MyDatabaseContext(databasePath))
{
GameConsole gmConsole = context.Consoles.First((console) => console.Identifier == "GC");
Console.WriteLine(gmConsole.InputButtonMap.Count); //Prints 0
gmConsole.ReadInJSONFields(); //This is what I want to eliminate
Console.WriteLine(gmConsole.InputButtonMap.Count); //Has the proper data after reading from JSON
}
This is inconvenient considering there will be more objects in the future. How can I have everything be read and written directly to and from the database, and have these fields be populated?
An example GameConsole in JSON form:
{
"Identifier": "GC",
"ValidInputs": [
"left",
"up",
"a",
"b"
],
"InputAxesMap": {
"left": {
"AxisVal": 0,
"MinAxisVal": 0.0,
"MaxAxisVal": -1.0,
"MaxPercentPressed": 100
},
"up": {
"AxisVal": 1,
"MinAxisVal": 0.0,
"MaxAxisVal": -1.0,
"MaxPercentPressed": 100
},
"InputButtonMap": {
"a": {
"ButtonVal": 0
},
"b": {
"ButtonVal": 1
}
}
}

Convert csv file to json using C# with no header

I would like to convert CSV file to JSON using C#. I know that there are a lot of similar questions but I couldnĀ“t find something that could help me.
Source file looks like this:
2019-12-01T00:00:00.000Z;2019-12-10T23:59:59.999Z
50;false;2019-12-03T15:00:12.077Z;005033971003;48;141;2019-12-03T00:00:00.000Z;2019-12-03T23:59:59.999Z
100;false;2019-12-02T12:38:05.989Z;005740784001;80;311;2019-12-02T00:00:00.000Z;2019-12-02T23:59:59.999Z
First line is not header (actually I don't know how to call it - header usually have names of each property).
The result should look like this
{
"transactionsFrom": "2019-12-01T00:00:00.000Z","transactionsTo": "2019-12-10T23:59:59.999Z",
"transactions": [{
"logisticCode": "005033971003",
"siteId": "48",
"userId":"141",
"dateOfTransaction": "2019-12-03T15:00:12.077Z",
"price": 50
},
{
"logisticCode": "005729283002",
"siteId": "80",
"userId":"311",
"dateOfTransaction": "2019-12-02T12:38:05.989Z",
"price": 100
}]
}
I would like to use POCO - maybe something like this:
public class Headers
{
public string TransactionFrom { get; set; }
public string TransactionTo { get; set; }
}
public class Results
{
public string logisticCode { get; set; }
public string siteId { get; set; }
public string userId { get; set; }
public string dateOfTransaction { get; set; }
public string price { get; set; }
public string packSale { get; set; }
}
But the problem is I don't know how to continue. Maybe some example would help. I know I can use ChoETL, CsvHelper but I don't how.
This code might help you
Step1 - Create model class
public class Headers
{
public string TransactionFrom { get; set; }
public string TransactionTo { get; set; }
public List<Transaction> Transactions { get; set; }
}
public class Transaction
{
public string logisticCode { get; set; }
public string siteId { get; set; }
public string userId { get; set; }
public string dateOfTransaction { get; set; }
public string price { get; set; }
public string packSale { get; set; }
}
Step 2 - Split the file and read the records
string strInput = #"2019-12-01T00:00:00.000Z;2019-12-10T23:59:59.999Z
50;false;2019-12-03T15:00:12.077Z;005033971003;48;141;2019-12-03T00:00:00.000Z;2019-12-03T23:59:59.999Z
100;false;2019-12-02T12:38:05.989Z;005740784001;80;311;2019-12-02T00:00:00.000Z;2019-12-02T23:59:59.999Z";
var headers = new Headers();
var transactions = new List<Transaction>();
var csvrecords = strInput.Split(new[] { '\r', '\n' },StringSplitOptions.RemoveEmptyEntries);
int count = 1;
foreach(var record in csvrecords)
{
var values = record.Split(';');
if (count == 1)
{
headers.TransactionFrom = values[0];
headers.TransactionTo = values[1];
}
else
{
var transaction = new Transaction();
transaction.logisticCode = values[3].Trim();
transaction.siteId = values[4].Trim();
transaction.userId = values[5].Trim();
transaction.dateOfTransaction = values[2].Trim();
transaction.price = values[0].Trim();
transactions.Add(transaction);
}
count++;
}
headers.Transactions = transactions;
var jsonString = JsonConvert.SerializeObject(headers);
Console.WriteLine(jsonString);
Output -
{
"TransactionFrom": "2019-12-01T00:00:00.000Z",
"TransactionTo": "2019-12-10T23:59:59.999Z",
"Transactions": [
{
"logisticCode": "005033971003",
"siteId": "48",
"userId": "141",
"dateOfTransaction": "2019-12-03T15:00:12.077Z",
"price": "50",
"packSale": null
},
{
"logisticCode": "005740784001",
"siteId": "80",
"userId": "311",
"dateOfTransaction": "2019-12-02T12:38:05.989Z",
"price": "100",
"packSale": null
}
]
}
With Cinchoo ETL, you can do it as follows
Define class structures as below
public class Headers
{
public string TransactionFrom { get; set; }
public string TransactionTo { get; set; }
public List<Transaction1> Transactions { get; set; }
}
public class Transaction
{
[ChoFieldPosition(4)]
public string logisticCode { get; set; }
[ChoFieldPosition(5)]
public string siteId { get; set; }
[ChoFieldPosition(6)]
public string userId { get; set; }
[ChoFieldPosition(2)]
public string dateOfTransaction { get; set; }
[ChoFieldPosition(1)]
public string price { get; set; }
}
Parse the CSV, generate JSON as below
string csv = #"2019-12-01T00:00:00.000Z;2019-12-10T23:59:59.999Z
50;false;2019-12-03T15:00:12.077Z;005033971003;48;141;2019-12-03T00:00:00.000Z;2019-12-03T23:59:59.999Z
100;false;2019-12-02T12:38:05.989Z;005740784001;80;311;2019-12-02T00:00:00.000Z;2019-12-02T23:59:59.999Z";
string csvSeparator = ";";
using (var r = ChoCSVReader.LoadText(csv)
.WithDelimiter(csvSeparator)
.ThrowAndStopOnMissingField(false)
.WithCustomRecordSelector(o =>
{
string line = ((Tuple<long, string>)o).Item2;
if (line.SplitNTrim(csvSeparator).Length == 2)
return typeof(Headers);
else
return typeof(Transaction);
})
)
{
var json = ChoJSONWriter.ToTextAll(r.GroupWhile(r1 => r1.GetType() != typeof(Headers))
.Select(g =>
{
Headers master = (Headers)g.First();
master.Transactions = g.Skip(1).Cast<Transaction1>().ToList();
return master;
}));
Console.WriteLine(json);
}
JSON Output:
[
{
"TransactionFrom": "2019-12-01T00:00:00.000Z",
"TransactionTo": "2019-12-10T23:59:59.999Z",
"Transactions": [
{
"logisticCode": "005033971003",
"siteId": "48",
"userId": "141",
"dateOfTransaction": "false",
"price": "50"
}
{
"logisticCode": "005740784001",
"siteId": "80",
"userId": "311",
"dateOfTransaction": "false",
"price": "100"
}
]
}
]
I am not sure if i can help you with any codes as your source CSV is very confusing, but i'll try to give you some ideas that might work out.
Firstly, you don't need a model class. I mean, you can use it if you want, but seems unnecessary here.
Next up is reading the CSV file. As you haven't posted any codes related to that and also didn't mention any problem with reading the file, i assume you are reading the file properly. Reading the CSV and writing a JSON from it is relatively easy. However, the CSV file itself looks very confusing. How are you reading it tho? Are you reading it as plain text? Do you have column headers or atleast columns?
If you are reading the file as plain text, then i guess you only have one way. And that is splitting the string and construct a new string with the splitted values. Splitting should be relatively easy as you have ;(semi-colon) which is separating each column/data. So the basic idea is splitting the string and storing it in an array or list, something like this :
string[] values = myCSV.split(";");
Now all you need to do is, simply use the strings inside values to construct a new string. You can use the StringBuilder for that, or an easy way(not feasible tho) would be string concatenation. I personally would recommend you to go with the StringBuilder.
Guidelines:
StringBuilder in C#
Creating a new line in StringBuilder
Double quotes inside string
Hopefully this gives you some ideas.

Parsing JSON with JObject

I need to parse a JSON, I am already parsing the first part of the record but I am having a problem with a sub record. This is my code:
List<JToken> results = new List<JToken>();
List<JToken> results2 = new List<JToken>();
using (var streamReader = new StreamReader(httpResponse.GetResponseStream()))
{
result = streamReader.ReadToEnd();
results = JObject.Parse(result).SelectToken("record").ToList();
}
List<Record> users = new List<Record>();
foreach (JObject token in results)
{
Record user = new Record();
user.id = Int32.Parse(token["id"].ToString());
user.full_name = token["full_name"].ToString();
user.email = token["email"].ToString();
//role.RoleName = token.SelectToken("name").ToString();
}
That's working perfectly but I have issues parsin a string that's a bit deeper. This is the JSON:
{
"record": [
{
"id": 2,
"institution_id": 1,
"full_name": "",
"email": "",
"role_id": 2,
"created": "2015-01-13 01:18:52.370379",
"updated": "2015-01-22 23:58:44.103636",
"branch_id": 1,
"Branch_by_branch_id": {
"id": 1,
"institution_id": 1,
"branch_name": "Test Branch"
}
}
]
}
I want to get the "branch_name" inside Branch_by_branch_id. How can I access it with Jobject?
If your JSON is this
{
"record": [
{
"id": 26,
"full_name": "",
"email": "",
"branch_id": 1,
"Branch_by_branch_id": {
"id": 1,
"institution_id": 1,
"branch_name": "NAME"
}
}
]
}
Have classes like this:
public class BranchByBranchId
{
public int id { get; set; }
public int institution_id { get; set; }
public string branch_name { get; set; }
}
public class Record
{
public int id { get; set; }
public string full_name { get; set; }
public string email { get; set; }
public int branch_id { get; set; }
public BranchByBranchId Branch_by_branch_id { get; set; }
}
public class RootObject
{
public List<Record> record { get; set; }
}
Then parse it and retrieve the value like this.
var root = JsonConvert.DeserializeObject<RootObject>(json);
var branchName = root[0].Branch_by_branch_id.branch_name;
I always prefer to access my JSON objects like this, because I like having my objects as native C# classes. The classes were generated by json2csharp.

how to create a json format using json.net in c#

I need a final json format as follows and that should be dynamic.
{
"product_items" :
[
{
"_at" : 1,
"product_id" : "999"
},
{
"_at" : 2,
"quantity" : 2.00
},
{
"_delete_at" : 3
}
]
}
How to create a json format as above in the code._at field is dynamic.sometimes it might be 2 and sometimes it might be 10.I dont have idea on to generate the json dynamically in c#.
class Test
{
public ProductItem[] product_items { get; set; }
class ProductItem
{
public int[] _at { get; set; }
public int[] _delete { get; set; }
public int[] quantity { get; set; }
public string[] product_id{get;set;}
}
}
i have create the the properties for json as above.
I'm using Newtonsoft library
Your class should look more like this:
public class ProductItem
{
public int _at { get; set; }
public string product_id { get; set; }
public double? quantity { get; set; }
public int? _delete_at { get; set; }
}
public class ProductItemObject
{
public List<ProductItem> product_items { get; set; }
}
A example on serializing :
List<ProductItem> list = new List<ProductItem>();
ProductItemObject o = new ProductItemObject { product_items = list };
var item1 = new ProductItem { _at = 1, product_id = "001" };
var item2 = new ProductItem { _at = 2, quantity = 2.00 };
var item3 = new ProductItem { _delete_at = 3 };
list.Add(item1);
list.Add(item2);
list.Add(item3);
string json = JsonConvert.SerializeObject(o, Formatting.Indented);
// json string :
// {
// "product_items": [
// {
// "_at": 1,
// "product_id": "001",
// "quantity": null,
// "_delete_at": null
// },
// {
// "_at": 2,
// "product_id": null,
// "quantity": 2.0,
// "_delete_at": null
// },
// {
// "_at": 0,
// "product_id": null,
// "quantity": null,
// "_delete_at": 3
// }
// ]
//}
An alternative full dynamic that gets u the same Json string without any model :
var jsonObject = new JObject();
dynamic objectList = jsonObject;
objectList.product_items = new JArray() as dynamic;
dynamic item = new JObject();
item._at = 1;
item.product_id = "999";
objectList.product_items.Add(item);
item = new JObject();
item._at = 2;
item.quantity = 2.00;
objectList.product_items.Add(item);
item = new JObject();
item._delete_at = 3;
objectList.product_items.Add(item);
string json = Newtonsoft.Json.JsonConvert.SerializeObject(jsonObject, Formatting.Indented);
Well, if I understand you properly and you just need to be able to generate that json, the product list should be dynamic with maybe anonymous classes then:
public class Products
{
public Products()
{
product_items = new List<dynamic>();
}
public List<dynamic> product_items { get; set; }
}
products.product_items.Add(new { _at = 1, product_id = "999" });

Categories

Resources