There is a line {"level": [{"level": 1, "points": 0, "name": "Some"}, {"level": 2, "points": 50, "name": "Second level "}, {" level ": 3," points ": 100," name ":" third level "}]}
How to fix the existing code or to add to get at the request when the exact same line?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Runtime.Serialization;
using System.ComponentModel;
using ServiceStack.ServiceHost;
namespace MSWA.Classes
{
[DataContract]
[Description("Get config")]
[RestService("/gconf")]
public class GameConfiguration
{
[DataMember]
public string puid { get; set; }
}
[DataContract]
public class GameConfigurationResponse
{
[DataMember]
public LevelList ll;
[DataMember]
public string TestResponse { get; set; }
}
// Level List
[DataContract]
public class LevelList
{
[DataMember]
public List<Level> level { get; set; }
}
// Desc one level
[DataContract]
public class Level
{
[DataMember]
public int level { get; set; }
[DataMember]
public int points { get; set; }
[DataMember]
public string name { get; set; }
}
/// Create your Web Service implementation
public class GameConfigurationService : IService<GameConfiguration>
{
public object Execute(GameConfiguration request)
{
// Original data
string respValue = "";
respValue = request.puid;
if (respValue == null || respValue == "0") respValue = "0";
Level lvl = new Level(){level=1, points=0, name=""};
LevelList llist = new LevelList();
llist.level.Add(lvl);
return new GameConfigurationResponse
{
ll = llist
};
}
}
}
I hope I have understood your question. I think you are asking how to update your existing code so that it outputs this object:
{
"level": [
{"level": 1, "points": 0, "name": "Some"},
{"level": 2, "points": 50, "name": "Second level"},
{"level": 3, "points": 100, "name": "Third level"}
]
}
You should remove these lines:
Level lvl = new Level(){level=1, points=0, name=""};
LevelList llist = new LevelList();
llist.level.Add(lvl);
And replace with these:
LevelList llist = new LevelList();
llist.level = new List<Level>();
llist.level.Add(new Level { level = 1, points = 0, name = "Some" });
llist.level.Add(new Level { level = 2, points = 50, name = "Second level" });
llist.level.Add(new Level { level = 3, points = 100, name = "Third level" });
Update:
I presume from your comment you want to change GameConfigurationResponse to just output the List<Level> without having the LevelList object?
[DataContract]
public class GameConfigurationResponse
{
[DataMember]
public List<Level> level { get; set; }
}
So the corresponding Execute method would be:
public object Execute(GameConfiguration request)
{
// Original data
string respValue = request.puid ?? "0";
return new GameConfigurationResponse
{
level = new List<Level> {
new Level { level = 1, points = 0, name = "Some" },
new Level { level = 2, points = 50, name = "Second level" },
new Level { level = 3, points = 100, name = "Third level" }
}
};
}
I am not sure what you are using respValue for. I have simplified it to string respValue = request.puid ?? "O"; That will set respValue to request.puid unless it is null, in which case it will be set to 0. But you aren't using this value, at least not in the code posted.
Related
I am attempting to deserialize a JSON array via an SSIS source script component in C# using Newtonsoft JSON.net, but I'm running into the following error when I try to build the SSIS project:
CS0029: Cannot implicitly convert type 'System.Collections.Generic.List<ScriptMain.Order> to <ScriptMain.Order'
I suspect it's something to do with the Order class not being defined as a list, but I'm fairly new to C# and I really don't know, so would really appreciate any advice.
This was working correctly for a JSON string before I attempted to change the code to handle an array - i.e. in the code I changed
Order order = JsonConvert.DeserializeObject<Order>(record);
to
Order order = JsonConvert.DeserializeObject<List<Order>>(record);
Here is the JSON array - it's just a typical order / orderline scenario where one order can have multiple order lines.
[
{
"OrderID": 291,
"CustomerID": 1135,
"OrderDate": "2020-07-21",
"OrderLine": [
{
"OrderLineID": 1,
"ProductID": 2,
"Units": 1,
"ClientID": 2
},
{
"OrderLineID": 2,
"ProductID": 8,
"Units": 2,
"ClientID": 1
}
]
},
{
"OrderID": 292,
"CustomerID": 59,
"OrderDate": "2020-07-21",
"OrderLine": [
{
"OrderLineID": 1,
"ProductID": 5,
"Units": 1,
"ClientID": 1
},
{
"OrderLineID": 2,
"ProductID": 7,
"Units": 2,
"ClientID": 2
},
{
"OrderLineID": 3,
"ProductID": 9,
"Units": 1,
"ClientID": 3
}
]
}
]
and here is the C# from the script component in SSIS:
public override void CreateNewOutputRows()
{
/*
Add rows by calling the AddRow method on the member variable named "<Output Name>Buffer".
For example, call MyOutputBuffer.AddRow() if your output was named "MyOutput".
*/
string filePath = Connections.OrdersFile20200720.AcquireConnection(null).ToString();
using (StreamReader fileContents = new StreamReader(filePath))
{
while (fileContents.Peek() >= 0)
{
string record = fileContents.ReadLine();
//Order order = JsonConvert.DeserializeObject<Order>(record);
Order order = JsonConvert.DeserializeObject<List<Order>>(record); //this is failing
OrderOutputBuffer.AddRow();
OrderOutputBuffer.OrderID = order.OrderID;
OrderOutputBuffer.CustomerID = order.CustomerID;
OrderOutputBuffer.OrderDate = order.OrderDate;
foreach (OrderLine orderline in order.OrderLine)
{
OrderLineOutputBuffer.AddRow();
OrderLineOutputBuffer.OrderID = order.OrderID;
OrderLineOutputBuffer.OrderLineID = orderline.OrderLineID;
OrderLineOutputBuffer.ProductID = orderline.ProductID;
OrderLineOutputBuffer.Units = orderline.Units;
OrderLineOutputBuffer.ClientID = orderline.ClientID;
}
}
}
}
public class Order
{
public int OrderID { get; set; }
public int CustomerID { get; set; }
public DateTime OrderDate { get; set; }
public OrderLine[] OrderLine { get; set; }
}
public class OrderLine
{
public int OrderLineID { get; set; }
public int ProductID { get; set; }
public int Units { get; set; }
public int ClientID { get; set; }
}
}
Thanks!
I fixed this in the end:
public override void CreateNewOutputRows()
{
/*
Add rows by calling the AddRow method on the member variable named "<Output Name>Buffer".
For example, call MyOutputBuffer.AddRow() if your output was named "MyOutput".
*/
string json = File.ReadAllText("Z:\\DataTech Test\\Data\\Orders_20200720.json");
var records = JsonConvert.DeserializeObject<List<Order>>(json);
foreach (var r in records)
{
OrderOutputBuffer.AddRow();
OrderOutputBuffer.OrderID = r.OrderID;
OrderOutputBuffer.CustomerID = r.CustomerID;
OrderOutputBuffer.OrderDate = r.OrderDate;
foreach (OrderLine orderline in r.OrderLine)
{
OrderLineOutputBuffer.AddRow();
OrderLineOutputBuffer.OrderID = r.OrderID;
OrderLineOutputBuffer.OrderLineID = orderline.OrderLineID;
OrderLineOutputBuffer.ProductID = orderline.ProductID;
OrderLineOutputBuffer.Units = orderline.Units;
OrderLineOutputBuffer.NurseryID = orderline.NurseryID;
}
}
}
public class OrderLine
{
public int OrderLineID { get; set; }
public int ProductID { get; set; }
public int Units { get; set; }
public int NurseryID { get; set; }
}
public class Order
{
public int OrderID { get; set; }
public int CustomerID { get; set; }
public DateTime OrderDate { get; set; }
public List<OrderLine> OrderLine { get; set; }
}
public class Root
{
public List<Order> Order { get; set; }
}
}
I'm making a tool that needs to export a json. He needs to be in this format:
{
"version" : "2",
"mangas" : [ {
"manga" : [ "sample", "manganame", 1234567890, 0, 0 ],
"chapters" : [ {
"u" : "urlexample",
"r" : 1
}, {
"u" : "urlexample",
"r" : 1
}, {
"u" : "urlexample",
"r" : 1
} ]
} ]
}
And this is my code:
void createJson(String manganame, String mangaoid, String sourceid)
{
String[] mangainfo = { "/manga/" + mangaoid, manganame, sourceid, "0", "0" };
var root = new RootObject()
{
version = "2",
mangas = new List<Manga>()
{
new Manga()
{
manga = mangainfo,
chapters = new List<Chapter>()
{
new Chapter
{
u = "sample",
r = 1
}
}
}
}
};
var json = JsonConvert.SerializeObject(root);
File.WriteAllText(#"D:\path.txt", json);
Console.WriteLine(json);
}
I'm lost, if someone can help me. Already give a search on Google, but the answer didn't come up in my head, already trying for a few time, slowly I'm getting but now is time to ask for help lol
For the list I was talking about, I'll explain it. I have a sqlite DB that have various information from mangas etc... I execute a query where I filter by a id, "SELECT * FROM MangaChapter WHERE manga_id = 'someid'", then i put the result on a list using a for loop. In the DB chapter url is stored like that "mr-chapter-166165" this is why i have had to concat string in chapterList.add.
List<String> chapterList = new List<String>();
cmd.CommandText = "SELECT * FROM MangaChapter WHERE manga_id = '3252'";
reader = cmd.ExecuteReader();
while (reader.Read())
{
chapterList.Add("/pagesv2?oid=" + reader.GetString("oid"));
}
For reference this is what I'm using to manage the sqlite db https://www.nuget.org/packages/dotConnect.Express.for.SQLite/
In the list, each chapter is something like that "/pagesv2?oid=mr-chapter-166165", if I print all the list on the console we'll be having something like that:
/pagesv2?oid=mr-chapter-166165
/pagesv2?oid=mr-chapter-166166
/pagesv2?oid=mr-chapter-166167
Here are the classes I generated from the given JSON sample
public class Chapter
{
[JsonProperty("u")]
public string U { get; set; }
[JsonProperty("r")]
public int R { get; set; }
}
public class Manga
{
[JsonProperty("manga")]
public IList<object> MangaInfos { get; set; }
[JsonProperty("chapters")]
public IList<Chapter> Chapters { get; set; }
}
public class Example
{
[JsonProperty("version")]
public string Version { get; set; }
[JsonProperty("mangas")]
public IList<Manga> Mangas { get; set; }
}
and here the code to reproduce the give JSON sample
var d = new Example
{
Version = "2",
Mangas = new List<Manga>
{
new Manga()
{
MangaInfos = new List<object>{ "sample", "manganame", 1234567890, 0, 0 },
Chapters = new List<Chapter>
{
new Chapter()
{
U = "urlexample",
R = 1,
},
new Chapter()
{
U = "urlexample",
R = 1,
},
new Chapter()
{
U = "urlexample",
R = 1,
},
},
},
},
};
var json = JsonConvert.SerializeObject(d,Formatting.Indented);
Console.WriteLine(json);
The output looks like
{
"version": "2",
"mangas": [
{
"manga": [
"sample",
"manganame",
1234567890,
0,
0
],
"chapters": [
{
"u": "urlexample",
"r": 1
},
{
"u": "urlexample",
"r": 1
},
{
"u": "urlexample",
"r": 1
}
]
}
]
}
and live view at .net fiddle
Based on your comment, if you want to have various chapters for each "Manga", you have to change your data structure and that changes the Result Json you want.
maybe something like this?
public partial class Root
{
public long Version { get; set; }
public Mangas[] Mangas { get; set; }
}
public partial class Mangas
{
public Manga[] Manga { get; set; }
}
public partial class Chapter
{
public string U { get; set; }
public long R { get; set; }
}
public partial struct Manga
{
public long? Integer;
public string String;
public Chapter[] Chapters { get; set; }
}
Iterate through chapters. Solution below.
class Parent
{
public int Version { get; set; }
public List<Manga> mangas { get; set; }
}
class Manga
{
public List<object> manga { get; set; }
public List<Chapter> chapters { get; set; }
}
class Chapter
{
public string u { get; set; }
public int r { get; set; }
}
void createJson(String manganame, string mId, String mangaoid, long sourceid)
{
var json = new Parent()
{
Version = 2,
mangas = new List<Manga>()
{
new Manga()
{
manga = new List<object>{ "/manga/"+mangaoid, manganame, sourceid, 0, 0 },
chapters = Chapters(),
}
}
};
var sjson = JsonConvert.SerializeObject(json, Formatting.Indented);
File.WriteAllText(#"C:\Users\Izurii\Desktop\oi.json", sjson);
}
List<Chapter> Chapters()
{
List<Chapter> chapters = new List<Chapter>();
for(int i = 0; i < links.Count; i ++)
{
chapters.Add(
new Chapter()
{
u = links[i],
r = 1,
});
}
return chapters;
}
I have below class structures,
public class Student
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Message
{
public int Size { get; set; } = 10;
public Student Student { get; set; }
}
Now I have list of messages like,
var messages = new List<Message>
{
new Message{ Size=10, Student=new Student{Id=1, Name="N1" } },
new Message{ Size=20, Student=new Student{Id=2, Name="N2" } }
};
which I want to write in JSON using Newtonsoft.Json,
using (var f = File.CreateText("C:\\Temp\\test.json"))
{
f.Write(JsonConvert.SerializeObject(messages));
}
This give below JSON output,
[
{
"Size": 10,
"Student": {
"Id": 1,
"Name": "N1"
}
},
{
"Size": 20,
"Student": {
"Id": 2,
"Name": "N2"
}
}
]
But I would like below output (without size and only one time root element student),
{
"Student": [
{
"Id": 1,
"Name": "N1"
},
{
"Id": 2,
"Name": "N2"
}
]
}
whats need to be done here? Thanks!
You need to refine your data to get desired result
first
var refindedResult = new { Students = messages.Select(m => m.Student) };
second pass it to json convertor
using (var f = File.CreateText("C:\\Temp\\test.json"))
{
f.Write(JsonConvert.SerializeObject(refindedResult ));
}
You can try to write a StudentModel class.
public class StudentModel
{
public IEnumerable<Student> Student { get; set; }
}
use linq get student collection from messages, then SerializeObject on it.
var res = new StudentModel()
{
Student = messages.Select(x => x.Student)
};
var json = JsonConvert.SerializeObject(res);
//f.Write(JsonConvert.SerializeObject(messages));
f.Write(JsonConvert.SerializeObject(messages.Select(m => m.Student)));
or, when you want a root object (Students, not Student)
f.Write(JsonConvert.SerializeObject(
new { Students = messages.Select(m => m.Student) } ));
I have two classes
public class MyObjects{
public bool Active {get; set;}
public List<OtherObject> OtherObjects {get; set;}
}
public class OtherObject {
public int Id {get; set;}
public bool Enabled {get; set;}
public string Address {get; set;}
public string Name {get; set;}
}
My current result is
MyObject { Active = true; },
OtherObjects: [OtherObject: { Id: 1, Name: 'First'},
OtherObject{Id: 2, Name: 'First'},
OtherObject{Id: 3, Name: 'Second'}];
I want to group them by Name so I would still have Active property and those OtherObjects inside would be grouped by OtherObject Name property. Is it possible to do so only using LINQ?
EDIT:
Final result should be json, that I will use in angular, so it should be something like this:
{
""Active"": true,
""OtherObjects"": [
{
""ObjectName"": ""Second"",
""ObjectOtherProperties"": [
{
""Id"": 1,
""Enabled"": false
},
{
""Id"": 2,
""Enabled"": true
}
],
""ObjectName"": ""Second"",
""ObjectOtherProperties"": [
{
""Id"": 1,
""Enabled"": false
}
],
]
}
}
Any suggestions how to achieve this? Maybe I must make other classes and somehow map them by grouping?
This is how I would do it, keeping it simple:
// 1. Add OtherObjectsDictionary
// 2. Block OtherObjects in the json serialization
public class MyObjects
{
public bool Active { get; set; }
[Newtonsoft.Json.JsonIgnore]
public List<OtherObject> OtherObjects { get; set; }
public Dictionary<string, List<OtherObject>> OtherObjectsDictionary { get; set; }
}
// 3. Block Name in the json serialization
public class OtherObject
{
public int Id { get; set; }
public bool Enabled { get; set; }
public string Address { get; set; }
[Newtonsoft.Json.JsonIgnore]
public string Name { get; set; }
}
// 4. Linq queries to achieve the grouped result
// 5. Serialize to Json
static void Main(string[] args)
{
var myObjects = new MyObjects() { Active = true, OtherObjects = new List<OtherObject>() };
myObjects.OtherObjects.Add(new OtherObject { Id = 1, Name = "First" });
myObjects.OtherObjects.Add(new OtherObject { Id = 2, Name = "First" });
myObjects.OtherObjects.Add(new OtherObject { Id = 3, Name = "Second" });
myObjects.OtherObjectsDictionary = new Dictionary<string, List<OtherObject>>();
var distinctNames = myObjects.OtherObjects.Select(otherObject => otherObject.Name).Distinct();
foreach(var distinctName in distinctNames)
{
var groupedObjectsList = myObjects.OtherObjects.Where(otherObject => otherObject.Name == distinctName).ToList();
myObjects.OtherObjectsDictionary.Add(distinctName, groupedObjectsList);
}
var outputJson = Newtonsoft.Json.JsonConvert.SerializeObject(myObjects);
}
This is the json result:
{
"Active": true,
"OtherObjectsDictionary": {
"First": [
{
"Id": 1,
"Enabled": false,
"Address": null
},
{
"Id": 2,
"Enabled": false,
"Address": null
}
],
"Second": [
{
"Id": 3,
"Enabled": false,
"Address": null
}
]
}
}
I hope it helps.
You may also use the System.Web.Extensions .dll as Add References for framework 4.0 projects (not 4.0 Client Profile).
Then add using inside your class.
I also applied a different approach, a more-or-less DB like normalization.
List of classes
public class MyObjects
{
public bool Active { get; set; }
public List<ObjectName> OtherObjects { get; set; }
}
public class ObjectName
{
public string Name { get; set; }
public List<OtherObject> OtherObjectProperties { get; set; }
}
public class OtherObject
{
public int Id { get; set; }
public bool Enabled { get; set; }
[ScriptIgnore]
public string Address { get; set; }
[ScriptIgnore]
public string Name { get; set; }
}
populate the records..
List<OtherObject> oList = new List<OtherObject>();
oList.Add(new OtherObject() { Id = 2, Name = "First" });
oList.Add(new OtherObject() { Id = 3, Name = "Second" });
// each name with objects
List<ObjectName> oNames = new List<ObjectName>();
oNames.AddRange(oList.Select(p => new ObjectName() {
Name = p.Name
, OtherObjectProperties = oList.Where(p1 => p1.Name == p.Name).ToList()
}).Distinct()
);
// parent object with with object names
MyObjects mo = new MyObjects() { Active = true, OtherObjects = oNames };
and finally, the javascript serializer..
JavaScriptSerializer jss = new JavaScriptSerializer();
string b = jss.Serialize(mo);
string b should give you the output like below..
{
"Active":true
,"OtherObjects":[
{
"Name":"First"
,"OtherObjectProperties":[
{
"Id":2
,"Enabled":false}
]},
{
"Name":"Second"
,"OtherObjectProperties":[
{
"Id":3
,"Enabled":false}
]
}]
}
Please advise if you're confused about any of the following.. :)
Could someone suggest a method of updating the items in the Cheese.Producers list?
I have the following classes:
class Producer
{
public string Name { get; set; }
public int Rating { get; set; }
public Producer()
{
}
public Producer(string name, int rating)
{
Name = name;
Rating = rating;
}
}
class Cheese
{
public string Name { get; set; }
public int Age { get; set; }
public string Taste { get; set; }
public List<Producer> Producers { get; set; }
public Cheese()
{
Producers = new List<Producer>();
}
public Cheese(string name, int age)
{
Name = name;
Age = age;
Producers = new List<Producer>();
}
public Cheese(string name, int age, string taste)
{
Name = name;
Age = age;
Taste = taste;
Producers = new List<Producer>();
}
}
In the main code I have an object(gouda) that I want to update based on a JSON read from a file.
static void Main(string[] args)
{
Producer prod1 = new Producer("prod1", 5);
Producer prod2 = new Producer("prod2", 6);
Producer prod3 = new Producer("prod3", 7);
Cheese gouda = new Cheese("Gouda", 5, "Mild");
gouda.Producers.Add(prod1);
gouda.Producers.Add(prod2);
gouda.Producers.Add(prod3);
string propertiesToBeAdded = File.ReadAllText("properties.txt");
JsonSerializerSettings jsonSerializerSettings = new JsonSerializerSettings
{
ObjectCreationHandling = ObjectCreationHandling.Reuse
};
JsonConvert.PopulateObject(propertiesToBeAdded, gouda, jsonSerializerSettings);
}
The JSON update file:
{
"Name": "Hard Blue",
"Taste": "Sharp",
"Producers": [
{
"Name": "prod1",
"Rating": 100
},
{
"Name": "prod3",
"Rating": 300
}
]
}
The major problem is that when the PopulateObject is called, instead of updating the Producers list items, 2 new members are added. The other fields seem to work just fine.
Any suggestions?
Try this:
Producer prod1 = new Producer("prod1", 5);
Producer prod2 = new Producer("prod2", 6);
Producer prod3 = new Producer("prod3", 7);
Cheese gouda = new Cheese("Gouda", 5, "Mild");
gouda.Producers.Add(prod1);
gouda.Producers.Add(prod2);
gouda.Producers.Add(prod3);
var propertiesToBeAdded = File.ReadAllText(#"C:\json path");
var settings = new JsonMergeSettings
{
MergeArrayHandling = MergeArrayHandling.Merge
};
var o1 = JObject.Parse(JsonConvert.SerializeObject(gouda));
o1.Merge(JObject.Parse(propertiesToBeAdded), settings);
var o = o1.ToString();
And you need to change your JSON format a bit :
{
'Name': 'Hard Blue',
'Taste': 'Sharp',
'Producers': [
{
'Name': 'prod1',
'Rating': 100
},
{
},
{
'Name': 'prod3',
'Rating': 300
}
]
}
Here we go:
Hope this helps.
I feel there is no way to accomplish simply what you want to do, with the constraints of the format you're using.
You want to retain unique producers, but are using an array of producers, wich has no way of preserving uniqueness.
So, AFAICT, you have two roads.
1 - you change the producers array in an json object, which would deserialize as a dictionary.
2 - you restrict the use of JSON.NET to the deserialization, and then implement a method "merge" in your Cheese class, with the relevant uniqueness checks.
If you need a refinement over this directions, let me know.
EDIT
First, change your Cheese class into this:
class Cheese
{
public string Name { get; set; }
public int Age { get; set; }
public string Taste { get; set; }
public Dictionary<String, Producer> Producers { get; set; }
public Cheese()
{
Producers = new Dictionary<String, Producer>();
}
public Cheese(string name, int age)
{
Name = name;
Age = age;
Producers = new List<Producer>();
}
public Cheese(string name, int age, string taste)
{
Name = name;
Age = age;
Taste = taste;
Producers = new List<Producer>();
}
}
And your Json accordingly:
{
"Name": "Hard Blue",
"Taste": "Sharp",
"Producers": {
"prod1": {
"Name": "prod1",
"Rating": 100
},
"prod3": {
"Name": "prod3",
"Rating": 300
}
}
}
Everything else should be equal.
The nice thing about the dictionary is that it takes care of the uniqueness of the keys.
I left some redundancy in the data, to simplify the code.
You could remove the
"Name": "prod1",
...
"Name": "prod3",
lines from the Json, populating the corresponding name property after deserialization, something like:
foreach(var prod in gouda.Producers.Keys)
{
gouda.Producers[prod].Name = prod;
}
Hope it helps.