I am attempting to use the Newtonsoft JSON library to parse a JSON string dynamically using C#. In the JSON is a named array. I would like to remove the square brackets from this array and then write out the modified JSON.
The JSON now looks like the following. I would like to remove the square bracket from the ProductDescription array.
{
"Product": "123",
"to_Description": [
{
"ProductDescription": "Product 1"
}
]
}
Desired result
{
"Product": "123",
"to_Description":
{
"ProductDescription": "Product 1"
}
}
I believe I can use the code below to parse the JSON. I just need some help with making the modification.
JObject o1 = JObject.Parse(File.ReadAllText(#"output.json"));
The to_Description property starts off as List<Dictionary<string,string>> and you want to take the first element from the List.
So, given 2 classes
public class Source
{
public string Product {get;set;}
public List<Dictionary<string,string>> To_Description{get;set;}
}
public class Destination
{
public string Product {get;set;}
public Dictionary<string,string> To_Description{get;set;}
}
You could do it like this:
var src = JsonConvert.DeserializeObject<Source>(jsonString);
var dest = new Destination
{
Product = src.Product,
To_Description = src.To_Description[0]
};
var newJson = JsonConvert.SerializeObject(dest);
Note: You might want to check there really is just 1 item in the list!
Live example: https://dotnetfiddle.net/vxqumd
You do not need to create classes for this task. You can modify your object like this:
// Load the JSON from a file into a JObject
JObject o1 = JObject.Parse(File.ReadAllText(#"output.json"));
// Get the desired property whose value is to be replaced
var prop = o1.Property("to_Description");
// Replace the property value with the first child JObject of the existing value
prop.Value = prop.Value.Children<JObject>().FirstOrDefault();
// write the changed JSON back to the original file
File.WriteAllText(#"output.json", o1.ToString());
Fiddle: https://dotnetfiddle.net/M83zv3
I have used json2csharp to convert the actual and desired output to classes and manipulated the input json.. this will help in the maintenance in future
First defined the model
public class ToDescription
{
public string ProductDescription { get; set; }
}
public class ActualObject
{
public string Product { get; set; }
public List<ToDescription> to_Description { get; set; }
}
public class ChangedObject
{
public string Product { get; set; }
public ToDescription to_Description { get; set; }
}
Inject the logic
static void Main(string[] args)
{
string json = "{\"Product\": \"123\", \"to_Description\": [ { \"ProductDescription\": \"Product 1\" } ]} ";
ActualObject actualObject = JsonConvert.DeserializeObject<ActualObject>(json);
ChangedObject changedObject = new ChangedObject();
changedObject.Product = actualObject.Product;
changedObject.to_Description = actualObject.to_Description[0];
string formattedjson = JsonConvert.SerializeObject(changedObject);
Console.WriteLine(formattedjson);
}
Why not:
public class EntityDescription
{
public string ProductDescription { get; set; }
}
public class Entity
{
public string Product { get; set; }
}
public class Source : Entity
{
[JsonProperty("to_Description")]
public EntityDescription[] Description { get; set; }
}
public class Target : Entity
{
[JsonProperty("to_Description")]
public EntityDescription Description { get; set; }
}
var raw = File.ReadAllText(#"output.json");
var source = JsonConvert.DeserializeObject<Source>(raw);
var target = new Target { Product = source.Product, Description = source.Description.FirstOrDefault() };
var rawResult = JsonConvert.SerializeObject(target);
Update For dynamic JSON
var jObject = JObject.Parse(File.ReadAllText(#"output.json"));
var newjObject = new JObject();
foreach(var jToken in jObject) {
if(jToken.Value is JArray) {
List<JToken> l = jToken.Value.ToObject<List<JToken>>();
if(l != null && l.Count > 0) {
newjObject.Add(jToken.Key, l.First());
}
} else {
newjObject.Add(jToken.Key, jToken.Value);
}
}
var newTxt = newjObject.ToString();
Related
I have a C# code that defines a constant JSON string and a corresponding POCO class. however i get an exception:
The JSON value could not be converted Path: $ | LineNumber: 0 | BytePositionInLine: 1.
Code
try
{
var filters = JsonSerializer.Deserialize <CmsContactsFilter>(FilterJson);
}
catch(Exception ex)
{
}
JSON
#"[{""cms"":""us-its"",""group"":[""ciso"",""cloudAdminsDistributionList"",""cloudAdmins""]},""cms"":""us-csdaudit"",""abc"":[""biso"",""costManagement""]},]";
POCO Class
public class CmsContactsFilter
{
public string Cms { get; set; }
public List<string> Group { get; set; }
}
Your json is not valid, here is the valid version of your json:
[
{
"cms": "us-its",
"group": [
"ciso",
"cloudAdminsDistributionList",
"cloudAdmins"
]
},
{
"cms": "us-csdaudit",
"group": [
"biso",
"costManagement"
]
}
]
Your code should be looks like this:
using System.Text.Json;
string filterJson = System.IO.File.ReadAllText("data.json");
var filters = JsonSerializer.Deserialize<List<CmsContactsFilter>>(filterJson);
foreach (var item in filters)
{
Console.WriteLine(item.cms+":");
foreach (var y in item.group)
{
Console.WriteLine("----"+y);
}
}
public class CmsContactsFilter
{
public string cms { get; set; }
public List<string> group { get; set; }
}
the name of the properties of the the CmsContactsFilter should be same with your json attributes names. if they are in lower-case format, your attribute name in the C# should be in the lower-case too.
your json is not valid, you need to add { to the second array item, and use an object collection for deserialization
var FilterJson = #"[{""cms"":""us-its"",""group"":[""ciso"",""cloudAdminsDistributionList"",""cloudAdmins""]},{""cms"":""us-csdaudit"",""abc"":[""biso"",""costManagement""]}]";
var filters = System.Text.Json.JsonSerializer.Deserialize <List<CmsContactsFilter>>(FilterJson);
and fix class
public class CmsContactsFilter
{
public string cms { get; set; }
public List<string> group { get; set; }
public List<string> abc { get; set; }
}
but as I understand your array has much more objects then 2. So you can try this code for the big json with different array names (if you had used Newtonsoft.Json this code could be significanly simplier)
JsonArray array = JsonNode.Parse(FilterJson).AsArray();
List<CmsContactsFilter> filters = new List<CmsContactsFilter>();
foreach (JsonObject item in array)
{
var obj = new CmsContactsFilter();
foreach (var prom in item.AsObject())
{
var name = prom.Key;
if (name == "cms")
{
obj.cms = prom.Value.ToString();
continue;
}
obj.groupName = name;
obj.group = System.Text.Json.JsonSerializer.Deserialize<List<string>>(prom.Value.ToString());
}
filters.Add(obj);
}
}
class
public class CmsContactsFilter
{
public string cms { get; set; }
public string groupName { get; set; }
public List<string> group { get; set; }
}
It is needed to parse JSONString into List. (List of instances)
I'm trying to use JSON.NET by Newtonsoft.
I have classes:
public class Item
{
public int ID { get; set; }
public string Name { get; set; }
public string Url { get; set; }
public string Manufactorers { get; set; }
}
The JSON string looks something like this:
[
{
"Column0":23.0,
"Column1":"Евроен",
"Column2":"https://www.123.com",
"Column3":"Фак"
},
{
"Column0":24.0,
"Column1":"Еил",
"Column2":"https://www.123.com",
"Column3":"Старт"
}
]
I've been trying to do something like this:
string JSONString = string.Empty;
JSONString = JsonConvert.SerializeObject(result);
List<Item> items = JsonConvert.DeserializeObject<List<Item>>(JSONString);
But it returns 0 and null.
I have no idea, how to fix it.
Also here I truy to parse Excel file. This code works, but after deserialization, I have just 0 and null.
var filePath = #"..\..\..\..\doc.xlsx";
using (var steam = File.Open(filePath, FileMode.Open, FileAccess.Read))
{
using (var reader = ExcelReaderFactory.CreateReader(steam))
{
var result = reader.AsDataSet().Tables["Лист1"];
string JSONString = string.Empty;
JSONString = JsonConvert.SerializeObject(result);
List<Item> items = JsonConvert.DeserializeObject<List<Item>>(JSONString);
}
}
The naming of JSON and your class does not match. This can be fixed using JsonProperty attributes:
[JsonProperty("Column0")]
public decimal ID { get; set; }
Second, JSON deserizlizer can not deserialize string "23.0" to int when there is decimal point. You can retype ID to decimal or double to make it work.
Little test here:
public class TestClass
{
[JsonProperty("Column0")]
public decimal ID { get; set; }
}
Then the deserialization works without errors:
var testClassJson = "{\"Column0\": 12.0}";
var i = JsonConvert.DeserializeObject<TestClass>(testClassJson);
string sampleString = "[{\"id\":\"1\",\"status\":302},{\"id\":\"2\",\"status\":302},{\"id\":\"3\",\"status\":302},{\"id\":\"4\",\"status\":302}]";
JArray json = JArray.Parse(sampleString );
TempValue t;
foreach(JObject obj in json)
{
t = new TempValue {
id =//id of json,
status=//state of json
};
}
i want to access value of json anonymous objec to assign to t object.
It is always good to work with a typed object to avoid typing mistakes. In this case create a class with the structure of the json string like so:
public class StatusObj
{
public string id { get; set; }
public int status { get; set; }
}
The deserialize the json string to list of your class like so:
List<StatusObj> obj = JsonConvert.DeserializeObject<List<StatusObj>>(sampleString);
And then you can loop through the list like so:
foreach (var item in obj)
{
var id = item.id;
var status = item.status;
}
The whole code look like this:
class Program
{
static void Main(string[] args)
{
string sampleString = "[{\"id\":\"1\",\"status\":302},{\"id\":\"2\",\"status\":302},{\"id\":\"3\",\"status\":302},{\"id\":\"4\",\"status\":302}]";
List<StatusObj> obj = JsonConvert.DeserializeObject<List<StatusObj>>(sampleString);
foreach (var item in obj)
{
var id = item.id;
var status = item.status;
}
}
}
public class StatusObj
{
public string id { get; set; }
public int status { get; set; }
}
NB. Newtonsoft.Json package needed to be installed. You can also convert any json to class here
By the indexer
foreach(JObject obj in json)
{
t = new TempValue {
id = obj["id"].ToString() ,
...
};
Object.Item Property (String)
Gets or sets the JToken with the specified property name.
I'm currently working on JSON string extraction using C#. My JSON string consist of an array with repetitive keys. Not sure if I'm describing it right since I'm new to this.
This is my JSON string
{"Index":
{ "LibraryName":"JGKing"
, "FormName":"AccountsPayable"
, "User":null
, "FilingPriority":null
, "FileDescription":null
, "Fields":
{"Field":
[
{ "Name":"invItemID"
, "Value":"6276"
}
,{ "Name":"invEntityCode"
, "Value":"16"
}
,{ "Name":"invVendorCode"
, "Value":"MIRUB01"
}
,{ "Name":"invNumber"
, "Value":"PWD5"
}
,{ "Name":"invDate"
, "Value":"2017-08-21"
}
,{ "Name":"invStatus"
, "Value":""
}
,{ "Name":"invCurrencyCode"
, "Value":"AU"
}
,{ "Name":"invCurrencyRate"
, "Value":"1"
}
,{ "Name":"invTax"
, "Value":"454.3"
}
, {"Name":"invTotal"
, "Value":"4997.27"
}
, {"Name":"invReceivedDate"
, "Value":"2017-09-06"
}
,{ "Name":"InvoiceLine1"
, "Value":"{\r\n \"invLineNumber\": \"1\",\r\n \"invPONumber\": \"\",\r\n \"invPOLineNo\": \"1\",\r\n \"invPOJobID\": \"\",\r\n \"invCostCode\": \"\",\r\n \"invCategory\": \"\",\r\n \"invGLCode\": \"61-01-49-6862.517\",\r\n \"invDescription\": \"\",\r\n \"invEntryType\": \"\",\r\n \"invAmount\": \"4542.97\",\r\n \"invTaxAmount\": \"454.3\",\r\n \"invTaxCode\": \"GST\",\r\n \"invAmountIncTax\": \"4997.27\"\r\n}"}]}}}
I need to extract the value of invItemID key which is inside the array.
I tried to serialize my json string from a class but it returns null in the List<>
Here's my code
public void CFExport(string jsonFile)
{
string ItemIDField;
string ItemIDValue;
using (StreamReader r = new StreamReader(jsonFile))
{
JsonSerializer s = new JsonSerializer();
var Idx = (JSONMain)s.Deserialize(r, typeof(JSONMain));
var flds = (Fields)s.Deserialize(r, typeof(Fields));
if (flds != null)
{
foreach (var _field in flds.Field)
{
ItemIDField = _field.Name;
ItemIDValue = _field.Value;
}
}
}
}
public class JSONMain
{
public Index Index { get; set; }
}
public class Index
{
public string LibraryName { get; set; }
public string FormName { get; set; }
public string User { get; set; }
public string FilingPriority { get; set; }
public string FileDescription { get; set; }
}
public class Fields
{
public List<Field> Field { get; set; }
}
public class Field
{
public string Name { get; set; }
public string Value { get; set; }
}
I hope you can help me.
Thanks in advance
Try to reflect the JSON file with your classes like this:
public class Index
{
public string LibraryName { get; set; }
public string FormName { get; set; }
public string User { get; set; }
public string FilingPriority { get; set; }
public string FileDescription { get; set; }
public Fields Fields { get; set; } //this line makes the difference
}
If you deserialize now, the fields should be populated automatically. I also advice you to use JsonConvert.Deserialze<>() since it is a bit easier (see documentation) and you are new to this topic.
Getting the value of invItemID could look like this:
public void CFExport(string jsonFile)
{
string ItemIDField = "invItemID";
string ItemIDValue;
using (StreamReader r = new StreamReader(jsonFile))
{
var Idx = JsonConvert.DeserializeObject<JSONMain>(r);
foreach(var field in Idx.Index.Fields.Field)
{
if(field.Name == ItemIDField)
{
ItemIDValue = field.Value;
}
}
}
}
Whoohoo. My first answer on Stackoverflow! I hope this helps you.
I need to extract the value of invItemID key which is inside the array.
You can retrieve value for your specified key invItemID from Field array by using JObject.
So you have no more need to manage classes for your json.
Here i created a console app for your demonstration purpose.
class Program
{
static void Main(string[] args)
{
//Get your json from file
string json = File.ReadAllText(#"Your path to json file");
//Parse your json
JObject jObject = JObject.Parse(json);
//Get your "Field" array to List of NameValuePair
var fieldArray = jObject["Index"]["Fields"]["Field"].ToObject<List<NameValuePair>>();
//Retrieve Value for key "invItemID"
string value = fieldArray.Where(x => x.Name == "invItemID").Select(x => x.Value).FirstOrDefault();
//Print this value on console
Console.WriteLine("Value: " + value);
Console.ReadLine();
}
}
class NameValuePair
{
public string Name { get; set; }
public string Value { get; set; }
}
Output:
I have this JSON array created in C#/aspx:
[
{
nome: "test",
apelido: "test"
}
]
And I want to create JSON like this:
{
success: 1,
error: 0,
gestor: "test",
cliente: [
{
nome: "test",
apelido: "test"
}
]
}
this is the code that i have:
var gestor = new JArray();
foreach (System.Data.DataRow item in com.Execute("select * from utilizadores").Rows)
{
gestor.Add(new JObject(new JProperty("nome", item["first_name"].ToString()),
new JProperty("apelido", item["last_name"].ToString())));
}
context.Response.Write(gestor);
I would just create a class for this (actually 2):
public class MyClass
{
public int success { get; set; }
public int error { get; set; }
public string gestor { get; set; }
public List<Cliente> cliente { get; set; }
}
public class Cliente
{
public string nome { get; set; }
public string apelido { get; set; }
}
And now you can loop to populate a list of these objects:
var myObj = new MyClass();
myObj.cliente = new List<Cliente>();
foreach (System.Data.DataRow item in com.Execute("select * from utilizadores").Rows)
{
myObj.cliente.Add(new Cliente()
{
nome = item["first_name"].ToString(),
apelido = item["last_name"].ToString()
};
}
// assuming that is successful
myObj.success = 1;
// not sure how you wanted this to be populated:
myObj.gestor = "test";
And now to serialize it you can just do:
context.Response.Write(JsonConvert.SerializeObject(myObj));
Charles' suggestion of anonymous classes is also perfectly fine if you have no other use for this class and it's not too complicated.
The most succinct way to do this is just with an anonymous class, if you are throwing this to some client side code and not really messing around with this exact object again elsewhere in server side code this is the easiest way to handle it.
var outputString = JsonConvert.SerializeObject(new {
success=1,
error=0,
gestor="test",
cliente = (from System.Data.DataRow i in com.Execute("select * from utilizadores").Rows
select new {
nome=item["first_name"],
apelido= item["last_name"]
}).ToArray()
});