I have a Excel file (.xlsx) with a sheet, which looks like this:
Name | Age | Country |
Nik 17 Switzerland
Thomas 28 Kuba
Waslim 12 Russia
I want to convert this excel sheet into JSON Format.
The result should look like this:
[
{
"Name":"Nik",
"Age":17,
"Country":"Switzerland"
},
{
"Name":"Thomas",
"Age":28,
"Country":"Kuba"
},
{
"Name":"Waslim",
"Age":12,
"Country":"Russia"
}
]
I would like to use the LightweightExcelReader framework. I know that there is a similar question already asked, but the answer uses OLEDB which shouldn't be best practice anymore. I would like to solve this transformation with a easier and faster framework.
IMPORTANT:
The number of rows and columns is dynamic and can vary, but the format of the excel sheet stays the from sheet to sheet the same.
Here is my attempt. As you can see i didn't manage alot and it's pretty basic. I managed to get the first row for the key in the JSON:
var excelReader = new ExcelReader(#"path\to\file\test.xlsx");
var sheetReader = excelReader[0];
IEnumerable<object> keys = sheetReader.Row(1);
How can I convert a Excel Sheet to JSON Format using the LightweightExcelReader Framework?
If you don't mind a dependency on Newtonsoft JSON you could do something like:
public static class ExcelJsonExtensionMethods
{
public static string ToJson(this SheetReader sheetReader)
{
IDictionary<int, string> HeaderNames = GetHeaderNames(sheetReader);
var jArray = new JArray();
while (sheetReader.ReadNext())
{
var jObject = new JObject();
do
{
var propertyName = HeaderNames[new CellRef(sheetReader.Address).ColumnNumber];
jObject[propertyName] = sheetReader.Value?.ToString();
} while (sheetReader.ReadNextInRow());
jArray.Add(jObject);
}
return jArray.ToString();
}
private static IDictionary<int, string> GetHeaderNames(SheetReader sheetReader)
{
var headerNames = new Dictionary<int, string>();
while (sheetReader.ReadNextInRow())
{
headerNames.Add(new CellRef(sheetReader.Address).ColumnNumber, sheetReader.Value?.ToString());
}
return headerNames;
}
}
Use it like:
var excelReader = new ExcelReader(#"path\to\file\test.xlsx");
var sheetReader = excelReader[0];
var sheetJson = sheetReader.ToJson();
Bear in mind that for this code to work:
The headers need to be on the first row
The header names need to be valid JSON property names
You can't have duplicate header names
There can't be any blank columns in the header
LightWeightExcelReader states on their github readme
If you want to map a spreadsheet to a collection of objects, use our sister project, ExcelToEnumerable
The sample on their sister project looks quite like what you are trying to achieve.
https://github.com/ChrisHodges/ExcelToEnumerable
public class Animal
{
public string Name { get; set; }
public string Colour { get; set; }
public int Legs { get; set; }
public decimal TopSpeed { get; set; }
}
IEnumerable<Animal> animals = "path/to/ExcelFile.xlsx".ExcelToEnumerable<Animal>();
and animals should then easily be serializable with Newtonsoft Json
using (StreamWriter file = File.CreateText(#"c:\animals.json"))
{
JsonSerializer serializer = new JsonSerializer();
serializer.Serialize(file, animals);
}
Related
I need to send data from my game server to the client through json and getting a large sum of data from the database and sending it creates an issue
Currently I am creating multiple list in the call to the database to get the data and now I am stuck because I have the data but in multiple list and I can't figure out how to return the data.
I feel like I should be converting it to JSON here and then returning the json string but its all just really confusing
public static void GetLobbyList() {
string query = "SELECT * FROM que";
MySqlCommand cmd = new MySqlCommand(query, MySQL.mySQLSettings.connection);
MySqlDataReader reader = cmd.ExecuteReader();
List<int> ids = new List<int>();
List<string> uids = new List<string>();
List<int> bets = new List<int>();
List<string> games = new List<string>();
while (reader.Read()) {
ids.Add((int)reader["id"]);
uids.Add((string)reader["uid"]);
bets.Add((int)reader["bet"]);
games.Add((string)reader["game"]);
}
reader.Close();
}
So here I am reading the info from the database and for lack of experience I am adding each data point to a list(which is really ugly and I know there must be a better way)
So essentially I Grab the data->Parse to json->Send string to client
If It is possible assuming the data returned is from a table with
id | uid | bet | game
I would Like to return an array in json that looks like
{
{
"id" : 1,
"uid" : "erjfh4982y9hf",
"bet" : 3,
"game" : "Snake"
}
{
"id" : 2,
"uid" : "gsegt34t",
"bet" : 2,
"game" : "Snake"
}
}
Im not too familiar with json and how it works but I do know that it is the only way to send large packets of data from my server to my client because everything has to be converted to bytes before it can be sent and my framework does not support converting list to bytes
To achieve what you are aiming for, you should create a class to hold the data you have retrieved from the database. In my case I called it GameObject and it's defined as follows.
public class GameObject
{
public int Id { get; set; }
public string Uid { get; set; }
public int Bet { get; set; }
public string Game { get; set; }
}
After retrieving the information from the database, you'll need to run code similar to the following.
var items = new List<GameObject>();
while (reader.Read())
{
items.Add(new GameObject
{
Id = (int)reader["id"],
Uid = (string)reader["uid"],
Bet = (int)reader["bet"],
Game = (string)reader["game"]
});
}
// Return the jsonPacket which will contain all the items in json format.
var jsonPacket = JsonConvert.SerializeObject(items);
In order for this to work, you'll need to reference the Newtonsoft.Json library from nuget. Open your package manager console and type the following command: Install-Package Newtonsoft.Json and it will set it up for you. At the top of our code you'll need to have using Newtonsoft.Json; to be able to use the classes inside the library to serialise to Json. On the receiving end you can pass the string to JsonConvert.DeserializeObject<T>() and you'll get back your list of objects.
You could use a list of objects and anonymous types. There's also a JSON serializer, System.Web.Script.Serialization.JavaScriptSerializer included if you add the System.Web.Extensions assembly to your references.
List<object> list = new List<object>();
while (reader.Read()) {
list.Add(new { id = (int)reader["id"],
uid = (string)reader["uid"],
bet = (int)reader["bet"],
game = (string)reader["game"], });
}
string json = new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(list);
How can I serialize a DataTable which contains a list of phone numbers, BodyOverride and ChannelType to this structure? The final JSON should look like the sample below. I see some posts that suggest using a Dictionary, but not I'm not sure if I can achieve this.
{
"Addresses": {
"+1713XXXXXXX": {
"BodyOverride": "sent",
"ChannelType": "SMS"
},
"+1832XXXXXXX": {
"BodyOverride": "this is a text from PINPOINT",
"ChannelType": "SMS"
}
}
}
Try a using class structure like this:
public class Payload
{
public Dictionary<string, Item> Addresses { get; set; }
}
public class Item
{
public string BodyOverride { get; set; }
public string ChannelType { get; set; }
}
Assuming you are starting from a DataTable that looks like this:
DataTable dataTable = new DataTable();
dataTable.Columns.Add("Address");
dataTable.Columns.Add("BodyOverride");
dataTable.Columns.Add("ChannelType");
dataTable.Rows.Add("+1713XXXXXXX", "sent", "SMS");
dataTable.Rows.Add("+1832XXXXXXX", "this is a text from PINPOINT", "SMS");
...you can easily convert it to the desired class structure like this:
var payload = new Payload
{
Addresses = dataTable.Rows
.Cast<DataRow>()
.ToDictionary(row => (string)row["Address"],
row => new Item
{
BodyOverride = (string)row["BodyOverride"],
ChannelType = (string)row["ChannelType"]
})
};
...and finally serialize it to JSON using a decent serialization library like Json.Net:
string json = JsonConvert.SerializeObject(payload, Formatting.Indented);
Fiddle: https://dotnetfiddle.net/b7Ckzs
Important note: the above solution assumes that the phone numbers in the Address column will be distinct across all rows in the DataTable. If they are not, then this solution will not work, because dictionary keys are required to be unique. In that case you will need to split the data into multiple batches, or find some other solution to deal with duplicates.
I am new in json. I want information of different users and add them to a dataGridView or dataTable or dataSet in c# (.net development). Information sample is (The json is valid):
{
"JrPwbApfIHbQhCUmVIoiVJcPYv93": {
"address": "Jessore",
"name": "Dev"
},
"iBRZAyn8TQTOgKTcByGOvJjL9ZB3": {
"address": "Bogra",
"name": "Kumar Saikat"
}
}
I want them like this :
User1 | Jessore | Dev
User2 | Bogra | Kumar Saikat
Even it would help if I could make a list for all of them.
I believe I was able to deserialise them (not sure at all) by
var model = JsonConvert.DeserializeObject<user>(json);
where user is a class.
public class Item
{
public string name;
public string address;
}
from this question-answer. From this tutorial I am able to get values if property is known. But in my case my property would be unknown, (string "User1","User2" would be random, since I will get them from a database). Any help and light on this matter would be greatly appreciated. Thank you in advance.
You're looking at a JSON dictionary, so just deserialize it as such:
public static Dictionary<string,Item> ParseJson(string source)
{
return JsonConvert.DeserializeObject<Dictionary<string,Item>>(source);
}
If you call it like this:
public static void Main()
{
var input = #"{'JrPwbApfIHbQhCUmVIoiVJcPYv93': {'address': 'Jessore','name': 'Dev' }, 'iBRZAyn8TQTOgKTcByGOvJjL9ZB3': {'address': 'Bogra','name': 'Kumar Saikat'}}";
var result = ParseJson(input);
foreach (var r in result)
{
Console.WriteLine("Key={0};Name={1};Address={2}", r.Key, r.Value.name, r.Value.address);
}
}
The output is:
Key=JrPwbApfIHbQhCUmVIoiVJcPYv93;Name=Dev;Address=Jessore
Key=iBRZAyn8TQTOgKTcByGOvJjL9ZB3;Name=Kumar Saikat;Address=Bogra
This example dumps the list to the console, but you could easily modify the for loop to add to a list instead.
See my example on DotNetFiddle
Can use the nuget package Newtonsoft.Json. This code gives you what you are looking for:
using System.Collections;
using System.Collections.Generic;
using Newtonsoft.Json;
namespace ConsoleApp1
{
internal class Program
{
static void Main(string[] args)
{
var json =
"{\"JrPwbApfIHbQhCUmVIoiVJcPYv93\":{\"address\":\"Jessore\",\"name\":\"Dev\"}," +
"\"iBRZAyn8TQTOgKTcByGOvJjL9ZB3\":{\"address\":\"Bogra\",\"name\":\"Kumar Saikat\"}}";
var o = JsonConvert.DeserializeObject(json);
var items = new List<Item>();
foreach (dynamic x in o as IEnumerable)
{
var i = new Item();
var y = x.First;
i.Name = y.name.Value;
i.Address = y.address.Value;
items.Add(i);
}
}
public class Item
{
public string Name { get; set; }
public string Address { get; set; }
}
}
}
Your situation is a bit strange as those autocreated names like
"JrPwbApfIHbQhCUmVIoiVJcPYv93" or else it's easier, but should be fairly easy code.
Keep in mind I use "dynamic" there which means problems will hit you at runtime NOT design time as it's not checked.
The correct way to deserialize would be as below
var model = JsonConvert.DeserializeObject<Dictionary<string, Item>>(data);
In the code sample you have posted, your "user" class name is Item but you are trying to deserialize using "User" in your code. Also please note that you cannot directly directly deserialize data into users list as it is present as a value of some random strings.
var model = JsonConvert.DeserializeObject<user>(json);
For your code to deserialize correctly, your json format should be as below :
{
{
"address": "Jessore",
"name": "Dev"
},
{
"address": "Bogra",
"name": "Kumar Saikat"
}
}
I'm trying to parse a json file with Json.net. The content of the json file is:
[
[ "240521000", "37.46272", "25.32613", "0", "71", "90", "15", "2016-07-18T21:09:00" ],
[ "237485000", "37.50118", "25.23968", "177", "211", "273", "8", "2015-09-18T21:08:00" ]
]
I created the following code:
WebClient wc = new WebClient();
string json = wc.DownloadString("data.json");
dynamic myObject = JsonConvert.DeserializeObject<dynamic>(json);
foreach (string item in myObject[0])
{
var x = item[0];
}
How can I loop through all the individual items without having a key?
You probably just need two nested foreach statements. Try something like this:
foreach (var items in myObject)
{
foreach (var item in items)
{
// do something
}
}
While diiN_'s answer answers the question, I don't think it's a good solution. Having had a look at the Marine Traffic API, it feels like they've made a poor JSON implementation, as the XML representation clearly has attribute names for the values. Their JSON should've been:
{"positions": ["position": {"mmsi": "311029000", "lat": "37.48617", "long": "24.37233", ...}]}
Because it isn't, we have a JSON string instead where it's a nested array, where the array is a two-dimensional array, and you'd have to hope the data model isn't changed to remove something, as you'd have to use an index to retrieve data.
However, if you look at the XML available from the API, the attributes have names. I would suggest that you instead download the XML, and parse this into an object - a model, in ASP.NET - which is strongly typed, and can be used more easily in a View.
Here's an example that I've got running. It uses XML parsing to first read the XML from the API, and then parse it to JSON, and finally an actual object.
First, the model class (Position.cs)
public sealed class Position
{
[JsonProperty("#MMSI")]
public string MMSI { get; set; }
[JsonProperty("#LAT")]
public string Latitude { get; set; }
[JsonProperty("#LON")]
public string Longitude { get; set; }
[JsonProperty("#SPEED")]
public string Speed { get; set; }
[JsonProperty("#HEADING")]
public string Heading { get; set; }
[JsonProperty("#COURSE")]
public string Course { get; set; }
[JsonProperty("#STATUS")]
public string Status { get; set; }
[JsonProperty("#TIMESTAMP")]
public string TimeStamp { get; set; }
}
Next, the parsing logic:
var client = new WebClient();
var xml = client.DownloadString("data.xml");
var doc = new XmlDocument();
doc.LoadXml(xml);
var json = JsonConvert.SerializeXmlNode(doc);
var positions = JObject.Parse(json).SelectToken("pos").SelectToken("row").ToObject<List<Position>>();
At the end of the parsing logic, you now have a list of Positions which you can pass to your view, and have it be strongly typed.
As a brief example:
// after you have the positions list
return View(positions);
Positions.cshtml
#model List<Positions>
<h2>Positions</h2>
#foreach (var position in Model)
{
<p>#position.MMSI (#position.Latitude, #position.Longitude)</p>
}
I hope this is useful to you. If you have any questions, drop me a comment.
{"pometek.net":{"status":"available","classkey":"dotnet"},"pometek.com":{"status":"available","classkey":"domcno"}}
I want to dispense this in table format. Need help.
You can use Json.NET to deserialize the json object into a C# class, and then map that class to a table format in asp.net
You shouldn't need a third-party library; the out-of-the-box JavaScriptSerializer can handle this.
class Item {
public string status { get; set; }
public string classkey { get; set; }
}
var jss = new System.Web.Script.Serialization.JavaScriptSerializer();
var input = "{\"pometek.net\":{\"status\":\"available\",\"classkey\":\"dotnet\"},\"pometek.com\":{\"status\":\"available\",\"classkey\":\"domcno\"}}";
var results = jss.Deserialize<Dictionary<string, Item>(input);
var query = results["pometek.net"].status; // = "available"
Displaying this as a table is a separate step.