How to encode text using File.WriteAllLines? - c#

I was trying to make a txt file, then rename the extension to .json, I have the encoding step and the WriteAllLines step done, but how do I encode the text?(I have the string needed to write)
Here's the code
string[] lines = { "{", "\"version\": 1,", "\"schema_version\": 2,", "",
$"\"id\": \"{textBox14.Text}\",", "", $"\"title\": \"{textBox7.Text}\",",
$"\"title_localized\": \"{textBox18.Text}\",", "", $"\"artist\": \"{textBox6.Text}\",",
$"\"artist_localized\": \"{textBox8.Text}\",", $"\"artist_source\": \"{textBox9.Text}\",",
$"", $"\"illustrator\": \"{textBox10.Text}\",", $"\"illustrator_source\": \"{textBox11.Text}\",",
$"", $"\"charter\": \"{textBox13.Text}\",", $"", "\"music\": {",
$"\"path\": \"{textBox4.Text}\"", "}", "\"music_preview\": {", $"\"path\": \"{textBox5.Text}\"", "}",
"\"background\": {", $"\"path\": \"{open3.FileName}\"", "}",
"\"charts\": [", "{", "\"type\": \"easy\",", $"\"name\": \"{textBox15.Text}\",",
$"\"difficulty\": {numericUpDown1.Value},", $"\"path\": \"textBox1.Text\"", "},",
"{", "\"type\": \"hard\",", $"\"name\": \"{textBox16.Text}\",", $"\"difficulty\": {numericUpDown2.Value},",
$"\"path\": \"{textBox2.Text}\"", "},", $"]", $"", "}" };
Encoding utf8WithoutBom = new UTF8Encoding(true);
File.WriteAllLines($#"C:\Users\Public\Desktop\level files\{textBox14.Text}\level.json", lines);
It was supposed to be something like this:
https://cytoid.io/level.json

Short answer:
Change this:
File.WriteAllLines($#"C:\Users\Public\Desktop\level files\{textBox14.Text}\level.json", lines);
to this:
File.WriteAllLines($#"C:\Users\Public\Desktop\level files\{textBox14.Text}\level.json", lines, utf8WithoutBom);
Long answer:
You shouldn't be generating JSON like this; you should be using a dedicated serializer. With your current solution, if a user enters an invalid character, your JSON will immediately become invalid. So, as a solution you could use Newtonsoft's JSON.Net. Here is an example:
Class definitions
public class Item
{
public int Version { get; set; }
public int SchemaVersion { get; set; }
public string Id { get; set; }
public string Title { get; set; }
public string TitleLocalized { get; set; }
public string Artist { get; set; }
public string ArtistLocalized { get; set; }
public string ArtistSource { get; set; }
public string Illustrator { get; set; }
public string IllustratorSource { get; set; }
public string Charter { get; set; }
public ItemMusic Music { get; set; }
public ItemMusicPreview MusicPreview { get; set; }
public ItemBackground Background { get; set; }
public List<ItemChart> Charts { get; set; }
}
public class ItemMusic
{
public string Path { get; set; }
}
public class ItemMusicPreview
{
public string Path { get; set; }
}
public class ItemBackground
{
public string Path { get; set; }
}
public class ItemChart
{
public string Type { get; set; }
public string Name { get; set; }
public int Difficulty { get; set; }
public string Path { get; set; }
}
Object initialization and serialization
var item = new Item
{
Version = 1,
SchemaVersion = 2,
Id = textBox14.Text,
Title = textBox7.Text,
TitleLocalized = textBox18.Text,
Artist = textBox6.Text,
ArtistLocalized = textBox8.Text,
ArtistSource = textBox9.Text,
Illustrator = textBox10.Text,
IllustratorSource = textBox11.Text,
Charter = textBox13.Text,
Music = new ItemMusic
{
Path = textBox4.Text
},
MusicPreview = new ItemMusicPreview
{
Path = textBox5.Text
},
Background = new ItemBackground
{
Path = open3.FileName
},
Charts = new List<ItemChart>
{
new ItemChart
{
Type = "easy",
Name = textBox15.Text,
Difficulty = numericUpDown1.Value,
Path = textBox1.Text
},
new ItemChart
{
Type = "hard",
Name = textBox16.Text,
Difficulty = numericUpDown2.Value,
Path = textBox2.Text
}
}
};
var settings = new JsonSerializerSettings()
{
ContractResolver = new DefaultContractResolver
{
NamingStrategy = new SnakeCaseNamingStrategy()
}
};
var json = JsonConvert.SerializeObject(item, settings);
File.WriteAllText($#"C:\Users\Public\Desktop\level files\{textBox14.Text}\level.json", json, new UTF8Encoding(true));
You could also use an anonymous type instead of creating the full class definition, of course:
var item = new {
Version = 1,
SchemaVersion = 2,
Charts = new List<object>
{
new {
Type = "easy"
}
}
}
and then just serialize this.

Related

How to get keys of objects as key value pairs?

I have class object and I need to store its values and keys in specific format.
public class AppSettings
{
public int TokenLifeTime { get; set; } = 450;
public List<string> Urls { get; set; } = new List<string>
{
"www.google.com",
"www.hotmail.com"
};
public List<ServersList> ServersList { get; set; } = new List<ServersList>
{
new ServersList {IsHttpsAllowed = false},
new ServersList {IsHttpsAllowed = true}
};
}
public class ServersList
{
public bool IsHttpsAllowed { get; set; }
}
I want to get keys in this format.
"AppSettings:TokenLifeTime" , 450
"AppSettings:Urls:0", "www.google.com"
"AppSettings:Urls:1", "www.hotmail.com"
"AppSettings:ServersList:0:IsHttpsAllowed", false
"AppSettings:ServersList:1:IsHttpsAllowed", true
Is there any way to get all keys as string recursively regardless of object depths. Above code is just an example in real case I have long list and lot more data.
I don't think that there is anything out of the box for this.
You would need to create something yourself and define your rules.
In its more primitive form, I'd start with this:
Type t = typeof(AppSettings);
Console.WriteLine("The {0} type has the following properties: ",
t.Name);
foreach (var prop in t.GetProperties())
Console.WriteLine(" {0} ({1})", prop.Name,
prop.PropertyType.Name);
Then add a rule for IEnumerable to handle them in iterations and so forth for objects and primitive value types.
I have a couple of examples for you:
Option 1:
public class AppSettings
{
public int TokenLifeTime { get; set; } = 450;
public Dictionary<string, ServersList> Urls { get; set; } = new Dictionary<string, ServersList>
{
{"www.google.com", new ServersList {IsHttpsAllowed = false}},
{ "www.hotmail.com", new ServersList {IsHttpsAllowed = true}}
};
}
public class ServersList
{
public bool IsHttpsAllowed { get; set; }
}
This option would group the values together but you would lose 'int' based index. Not sure if that is important.
Option 2:
public class AppSettings
{
public int TokenLifeTime { get; set; } = 450;
public List<KeyValuePair<string, ServersList>> Urls { get; set; } = new List<KeyValuePair<string, ServersList>>
{
new KeyValuePair<string, ServersList>("www.google.com",new ServersList {IsHttpsAllowed = false}),
new KeyValuePair<string, ServersList>("www.hotmail.com", new ServersList {IsHttpsAllowed = true})
};
public List<ServersList> ServersList { get; set; } = new List<ServersList>
{
new ServersList {IsHttpsAllowed = false},
new ServersList {IsHttpsAllowed = true}
};
}
public class ServersList
{
public bool IsHttpsAllowed { get; set; }
}
This option will retain 'int' based indexing and the values are still grouped. But feels clunky...
Option 3: (the one I would go with)
public class AppSettings
{
public int TokenLifeTime { get; set; } = 450;
public List<Server> ServersList { get; set; } = new List<Server>
{
new Server { Url = "www.google.com", IsHttpsAllowed = false},
new Server { Url = "www.hotmail.com", IsHttpsAllowed = true}
};
}
public class Server
{
public string Url { get; set; }
public bool IsHttpsAllowed { get; set; }
}
This option still gives you 'int' based indexing and it groups the data together (as it should be from what I understand in the example).

How to push to do a emdeded document in mongodb c# driver

i have a problem how to push a document into a another document to create a embeded document in c#.
my models look like :
public class ModelKnjiga
{
public ModelKnjiga() { }
[BsonId(IdGenerator = typeof(CombGuidGenerator))] // pojavljuje se greška kod BSON tipa podataka kod ID-a,preuzoteo s dokumentacije drivera 1.5
public Guid Id { get; set; }
[BsonElement("naziv")]
public string naziv { get; set; }
[BsonElement("autor")]
public string autor { get; set; }
[BsonElement("godina_izdanja")]
public string godina_izdanja { get; set; }
[BsonElement("izdavac")]
public string izdavac { get; set; }
[BsonElement("ocjena")]
public String ocjena { get; set; }
[BsonElement("čitam")]
public Boolean čitam { get; set; }
[BsonElement("završio")]
public Boolean završio { get; set; }
}
another model looks like :
public ModelKorisici () {
KnjigaLista = new List<ModelKnjiga>();
}
[BsonId] // pojavljuje se greška kod BSON tipa podataka kod ID-a,preuzoteo s dokumentacije drivera 1.5 CombGuidGenerator
public Guid Identifikator { get; set; }
[BsonElement("ime")]
public string ime { get; set; }
[BsonElement("prezime")]
public string prezime { get; set; }
[BsonElement("lozinka")]
public string lozinka { get; set; }
[BsonElement("email")]
public string email { get; set; }
[BsonElement("kor_ime")]
public string kor_ime { get; set; }
[BsonElement("uloga")]
public string uloga { get; set; }
public List<ModelKnjiga> KnjigaLista { get; set; }
}
and now i am tring to push a modelKnjiga into a modelKorisici
I am trying with this method...
public void dodajKnjiguKorisniku(ModelKnjiga knjiga, Guid id)
{
MongoCollection<ModelKorisici> korisniciKolekcija = GetTasksCollectionKlijenti();
try
{
var pronadiKorisnika = Query<ModelKorisici>.EQ(e => e.Identifikator, id);
var PushPodataka = Update<ModelKorisici>.Push(e => e.KnjigaLista, knjiga);
korisniciKolekcija.Update(pronadiKorisnika, PushPodataka);
}
catch (MongoCommandException ex)
{
string msg = ex.Message;
}
}
In robomongo, the object KnjigaLista is always Null...
Can somebody help?
I think Update is legacy.
(in your models you don't have to use strings only. Eg.: godina_izdanja could be DateTime(), and ocjena some numeric format...)
I made an (async) example with your models, hope it helps:
class Program
{
static void Main(string[] args)
{
MainAsync(args).GetAwaiter().GetResult();
Console.WriteLine("");
Console.WriteLine("press enter");
Console.ReadKey();
}
static async Task MainAsync(string[] args)
{
ModelKnjiga knga = new ModelKnjiga()
{
autor = "Author",
godina_izdanja = "2015",
izdavac = "izdavac",
naziv = "naziv",
ocjena = "20",
završio = true,
čitam = true
};
ModelKnjiga knga2 = new ModelKnjiga()
{
autor = "Author2",
godina_izdanja = "2016",
izdavac = "izdavac2",
naziv = "naziv2",
ocjena = "202",
završio = false,
čitam = false
};
ModelKnjiga knga3 = new ModelKnjiga()
{
autor = "Author3",
godina_izdanja = "2017",
izdavac = "izdavac3",
naziv = "naziv3",
ocjena = "203",
završio = false,
čitam = true
};
ModelKorisici mcor = new ModelKorisici()
{
email = "no#where.com",
ime = "ime",
KnjigaLista = new List<ModelKnjiga>() { knga, knga2 },
kor_ime = "kor_ime",
uloga = "uloga",
lozinka = "lozinka",
prezime = "prezime"
};
var client = new MongoClient();
var db = client.GetDatabase("KnjigaDB");
var korisici = db.GetCollection<ModelKorisici>("Korisici");
//After first run comment this line out
await korisici.InsertOneAsync(mcor);
//After first run UNcomment these lines
//var filter = Builders<ModelKorisici>.Filter.Eq("email", "no#where.com");
//var update = Builders<ModelKorisici>.Update.Push("KnjigaLista", knga3);
//await korisici.UpdateOneAsync(filter, update);
}
}
if you don't like async, change the last line with this:
korisici.UpdateOne(filter, update);

how to get Json nested properties to primary one

I have below scenario:
This is my class structure :
public class User
{
public string FirstName { get; set; }
public string LastName { get; set; }
public System.Collections.ObjectModel.Collection<Likes> Likes { get; set; }
}
public class Likes
{
public string Sport { get; set; }
public string Music { get; set; }
public string Food { get; set; }
public string Place { get; set; }
}
When I serialize object of User class then it will generate the below json string :
{"FirstName":"Naresh",
"LastName":"Parmar",
"Likes": [{"Sport":"Cricket",
"Music":"Classic",
"Food":"Gujarati",
"Place":"India"}]
}
I want to generate above json string like below:
{"FirstName":"Naresh",
"LastName":"Parmar",
"Sport":"Cricket",
"Music":"Classic",
"Food":"Gujarati",
"Place":"India"
}
I want the nested properties as primary one.
Any help would be appreciated.
Thanks in advance..
EDIT:
{"FirstName":"Naresh",
"LastName":"Parmar",
"Sport":"Cricket,Chess,Football",
"Music":"Classic",
"Food":"Gujarati",
"Place":"India"
}
It's really bad practice, since the code i'll post bellow doesn't have great maintainability, however if that's what you looking for, you can use this. Another class that have the format that you'd like, and have a method that adds a list of likes to the format you've required. That the class you should serialize to JSON:
class NestedUser
{
public string FirstName { get; set; }
public string LastName { get; set; }
public string Sport { get; set; }
public string Music { get; set; }
public string Food { get; set; }
public string Place { get; set; }
public void AddLikes(System.Collections.ObjectModel.Collection<Likes> likes)
{
foreach (Likes like in likes)
{
Sport += like.Sport + ",";
Music += like.Music + ",";
Food += like.Food + ",";
Place += like.Place + ",";
}
if (Sport != string.Empty)
{
Sport = Sport.Substring(0, Sport.Length - 1);
}
if (Music != string.Empty)
{
Music = Music.Substring(0, Music.Length - 1);
}
if (Food != string.Empty)
{
Food = Food.Substring(0, Food.Length - 1);
}
if (Place != string.Empty)
{
Place = Place.Substring(0, Place.Length - 1);
}
}
}
Since it's not only limited to Likes objects I'd suggest using dynamic objects. So the User class I propose is as follows:
public class User
{
public string FirstName { get; set; }
public string LastName { get; set; }
public dynamic Details { get; set; }
public User()
{
Details = new ExpandoObject();
}
public void AddSingleDetail(string key, string value)
{
var dict = this.Details as IDictionary<string, Object>;
if (dict.ContainsKey(key))
{
dict[key] += "," + value;
}
else
{
dict[key] = value;
}
}
public void AddDetails(object detailsObject)
{
var type = detailsObject.GetType();
foreach (var prop in type.GetProperties())
{
AddSingleDetail(prop.Name, prop.GetValue(detailsObject).ToString());
}
}
}
You can use it for adding single proerpties or adding an object as a whole. I used reflection to get all the property name and values and add them to the user details.
Sample usage:
static void Main(string[] args)
{
var user1 = new User() { FirstName = "Homer", LastName = "Simpson" };
user1.AddSingleDetail("Sport", "Bowling");
user1.AddSingleDetail("Sport", "Sleeping");
user1.AddSingleDetail("Food", "Donut");
user1.AddSingleDetail("Music", "Rock");
string flattenedHomer1 = ConvertUserToFlattenedJson(user1);
var user2 = new User() { FirstName = "Homer", LastName = "Simpson" };
var likes1 = new Likes() { Food = "Donut", Music = "Rock", Place = "Springfield", Sport = "Bowling" };
var likes2 = new Likes() { Food = "Steaks", Music = "Metal", Place = "Evergreen Terrace", Sport = "Sleeping" };
var proStuff = new ProfessionalStuff() { Title = "Boss" };
user2.AddDetails(likes1);
user2.AddDetails(likes2);
user2.AddDetails(proStuff);
string flattenedHomer2 = ConvertUserToFlattenedJson(user2);
}
And the method performing the JSON conversion is:
public static string ConvertUserToFlattenedJson(User u)
{
dynamic flatUser = new ExpandoObject();
flatUser.FirstName = u.FirstName;
flatUser.LastName = u.LastName;
var dict = u.Details as IDictionary<string, Object>;
foreach (var like in dict)
{
((IDictionary<string, Object>)flatUser)[like.Key] = like.Value;
}
string json = Newtonsoft.Json.JsonConvert.SerializeObject(flatUser);
return json;
}
In my sample above user2 is converted to the following JSON string which I believe is what you are looking for:
{
"FirstName": "Homer",
"LastName": "Simpson",
"Sport": "Bowling,Sleeping",
"Music": "Rock,Metal",
"Food": "Donut,Steaks",
"Place": "Springfield,Evergreen Terrace",
"Title": "Boss"
}
While concatenating strings you can check for null or duplicate values. I didn't handle that part.
For the sake of completeness, here's the ProfessionalStuff class I made up:
public class ProfessionalStuff
{
public string Title { get; set; }
}
Hope this helps.

Custom Jump lists in Windows Phone

I have been looking at this: http://code.msdn.microsoft.com/wpapps/Custom-LongList-Selector-bf8cb9ad and trying to incorporate into my app. However, its a little confusing since my data is loaded differently. Right now, I have two errors The best overloaded method match for CustomKeyGroup<.ViewModels.SoundData>.GetSoundGroups(System.Collections.Generic.List<.ViewModels.SoundData>)' has some invalid arguments
Argument 1: cannot convert from 'string' to 'System.Collections.Generic.List'
The error is at 'CustomKeyGroup.GetSoundGroups(mvm.Items);' from the mainpage.cs. I know the items is an issue. If you look at the link, they load the data differently w/ listmovie.add.
I know something is screwed up big time but since my data is loaded different, im struggling to get it working correctly.
Id like to have custom jumplist w/ headers by Groups (Alpha, Bravo, etc) located in my SoundModel. Here is a portion:
namespace T.ViewModels
{
public class SoundModel: BindableBase
{
public SoundGroup NewAdds { get; set; }
public SoundGroup Software { get; set; }
}
public bool IsDataLoaded { get; set; }
public void LoadData()
{
// Load data into the model
Software = CreateSoftwareGroup();
NewAdds = CreateNewAddsGroup();
IsDataLoaded = true;
}
private SoundGroup CreateNewAddsGroup()
{
SoundGroup data = new SoundGroup();
data.Title = "New";
string basePath = "assets/audio/newadds/";
data.Items.Add(new SoundData
{
Title = "Test1",
FilePath = basePath + "Test.mp3",
Groups = "Alpha"
});
data.Items.Add(new SoundData
{
Title = "Test2",
FilePath = basePath + "Test2.mp3",
Groups="Bravo"
});
data.Items.Add(new SoundData
{
Title = "Test3",
FilePath = basePath + "Test3.mp3",
Groups= "Zulu"
});
private SoundGroup CreateSoftwareGroup()
{
SoundGroup data = new SoundGroup();
data.Title = "Software";
string basePath = "assets/audio/Software/";
data.Items.Add(new SoundData
{
Title = "Test1",
FilePath = basePath + "Test.mp3",
Groups = "Alpha"
});
data.Items.Add(new SoundData
{
Title = "Test2",
FilePath = basePath + "Test2.mp3",
Groups="Bravo"
});
data.Items.Add(new SoundData
{
Title = "Test3",
FilePath = basePath + "Test3.mp3",
Groups= "Zulu"
});
Here is the relevant mainpage.cs:
SoundData mvm = new SoundData();
this.LongList.ItemsSource = CustomKeyGroup<SoundData>.GetSoundGroups(mvm.Items);
SoundGroup:
{
public class SoundGroup
{
public SoundGroup()
{
Items = new List<SoundData>();
}
public List<SoundData> Items { get; set; }
public string Title { get; set; }
public string Groups { get; set; }
}
}
SoundData :
{
public class SoundData : ViewModelBase
{
public string Title { get; set; }
public string FilePath { get; set; }
public string Items { get; set; }
public string Groups { get; set; }
public RelayCommand<string> SaveSoundAsRingtone { get; set; }
private void ExecuteSaveSoundAsRingtone(string soundPath)
{
App.Current.RootVisual.Dispatcher.BeginInvoke(() =>
{
SaveRingtoneTask task = new SaveRingtoneTask();
task.Source = new Uri("appdata:/" + this.FilePath);
task.DisplayName = this.Title;
task.Show();
}
);
}
public SoundData()
{
SaveSoundAsRingtone = new RelayCommand<string>(ExecuteSaveSoundAsRingtone);
}
}
}
So far from I what can see you should be calling the function as below
SoundModel svm = new SoundModel();
svm.LoadData();
this.LongList.ItemsSource = CustomKeyGroup<SoundData>.GetSoundGroups(svm.Software.Items);
or
this.LongList.ItemsSource = CustomKeyGroup<SoundData>.GetSoundGroups(svm.NewAdds.Items);
the reason is that you need to pass a Generic.List<.ViewModels.SoundData> in method GetSoundGroups and the list is contained in SoundGroup class. Since your data loaded is within SoundModel class so I could probably think of the above implementation only.

JSON Parser Element not found

This is my JSON
{
"State of Origin 2014":{
"1471137":{
"EventID":1471137,
"ParentEventID":1471074,
"MainEvent":"State Of Origin Series 2014",
"Competitors":{
"ActiveCompetitors":3,
"Competitors":[
{
"Team":"New South Wales (2 - 1)",
"Win":"2.15",
},
{
"Team":"New South Wales (3 - 0)",
"Win":"3.05",
},
{
"Team":"Queensland (2 - 1)",
"Win":"3.30",
}
],
"TotalCompetitors":3,
"HasWinOdds":true
},
"EventStatus":"Open",
"IsSuspended":false,
"AllowBets":true
},
"3269132":{
"EventID":3269132,
"ParentEventID":0,
"MainEvent":"New South Wales v Queensland",
"Competitors":{
"Margin1Low":1,
"Competitors":[
{
"Name":"New South Wales",
"Win":"1.60",
},
{
"Name":"Queensland",
"Win":"2.35",
}
],
"HasWinOdds":true,
"TotalOddsColumns":2,
"MarketCount":1,
"PerformVideo":false
},
"EventStatus":"Open",
"IsSuspended":false,
"AllowBets":true
}
}
}
I am using JSON.Net and everything is working fine but in some of my data some element fields are missing for example i am getting Team element inside Competitors as
Teams = from JObject comps in value["Competitors"]["Competitors"]
select (string)comps["Team"]
But in some data Team element is missing and i want to grap Name Element so i am getting Object reference not set to an instance of an object. Error.
This is my code
var query =
from JProperty ev in obj.AsJEnumerable()
from JProperty evid in ev.Value.AsJEnumerable()
let value = (JObject)evid.Value
select new Person
{
EventID = (string)value["EventID"],
Description = (string)value["MainEvent"],
OutcomeDateTime = (string)value["OutcomeDateTime"],
EventStatus = (string)value["EventStatus"],
Teams = from JObject comps in value["Competitors"]["Competitors"]
select (string)comps["Team"]
};
foreach (var b in query)
{
string description = b.Description;
string OutcomeDateTime = b.OutcomeDateTime;
IEnumerable<string> _team = b.Teams;
foreach (var teams in _team)
{
string team = teams.ToString();
}
Console.WriteLine(description);
Console.WriteLine(OutcomeDateTime);
}
How can i get Name element value if Team element does not exist ?
You can deserialize your json to concrete classes
var obj = JsonConvert.DeserializeObject < Dictionary<string, Dictionary<string,RootObject>>>(json);
public class Competitor
{
public string Team { get; set; }
public string Win { get; set; }
}
public class CompetitorsClass
{
public int ActiveCompetitors { get; set; }
public List<Competitor> Competitors { get; set; }
public int TotalCompetitors { get; set; }
public bool HasWinOdds { get; set; }
}
public class RootObject
{
public int EventID { get; set; }
public int ParentEventID { get; set; }
public string MainEvent { get; set; }
public CompetitorsClass Competitors { get; set; }
public string EventStatus { get; set; }
public bool IsSuspended { get; set; }
public bool AllowBets { get; set; }
}
BTW: What is OutcomeDateTime? there is no such field in your json.
The following will work. Use the null-coalescing operator to grab "Name" if "Team" is null. http://msdn.microsoft.com/en-us/library/ms173224.aspx
Teams = from JObject comps in value["Competitors"]["Competitors"]
select (string)comps["Team"] ?? (string)comps["Name"]

Categories