I can't access the json file in c# Xamarin - c#

I already put the access as being 'read/write' so everyone including me can read and write to the json file. However, the code is still sending out an UnauthorizedAccessException afterwards. This is the code:
public static void read_json(string path)
{
using (StreamReader r = new StreamReader("/Users/steve/Downloads/city_list.json"))
{
string json = r.ReadToEnd();
List<City_Data> items = JsonConvert.DeserializeObject<List<City_Data>>(json);
foreach (City_Data item in items)
{
var key = item.name;
var value = item.id;
dict.Add(key, value);
}
}
}
while this is part of the json file which I have been wanting to access and read from:
[
{
"id": 833,
"name": "Ḩeşār-e Sefīd",
"state": "",
"country": "IR",
"coord": {
"lon": 47.159401,
"lat": 34.330502
}
},
...
]

Make all files writeable when checking out of source control.
Call the Attrib MSBuild task before the transformation to remove the read-only file attribute.
For example:
<Attrib Files="/Users/steve/Downloads/city_list.json" Normal="true"/>
Call the Exec MSBuild task before the transformation to remove the read-only file attribute.
For example:
<Exec Command="attrib -R "/Users/steve/Downloads/city_list.json""/>

Related

Deserializing JSON using UnityEngine.JsonUtility returns null list

I am trying to mod a Unity game using BepInEx. I want to read a list of a type of class I've created from a JSON, then read each object from that class. I used UnityEngine.JsonUtility to do this and created a wrapper class containing my list.
[System.Serializable]
public class StarSignDataList
{
public List<StarSignData> starSigns;
}
// Stores all data pertaining to star signs as read from JSON file.
[System.Serializable]
public class StarSignData
{
public string name;
public int id;
public string description;
}
Then I read the json file from the correct file path, parsing that information into a string and called the JsonUtility.FromJason() method to convert the string into my StarSignDataList class.
// Reads all star sign data from JSON and assigns values to list.
public static void InitializeData()
{
log.LogInfo("Initializing Star Sign data.");
string json = File.ReadAllText("BepInEx/plugins/StarSigns/starsigns.json");
log.LogInfo(json);
StarSignDataList list = UnityEngine.JsonUtility.FromJson<StarSignDataList>(json);
log.LogWarning(list.starSigns.Count == 0 ? "Not null" : "Null!");
log.LogInfo(list.starSigns[0].name);
signs = list.starSigns;
foreach (StarSignData data in signs)
{
log.LogInfo(data.name);
}
}
When I print out the contents of my json immediately after reading it, it comes out as expected, looking exactly like my json file. However when I convert the json string into my list class, the list is completely empty and then throws a NullReferenceException when trying to print the first object. I've trying using arrays instead of lists, I've checked that my json is correctly written, I've pored over countless google search results without success.
Here is my json file.
{
"starSigns": [
{
"name": "Sign of the Fool",
"id": 0,
"description": "You are of normal birth."
},
{
"name": "Sign of Loki",
"id": 1,
"description": "The sign of the god of betrayal shone above your birth place."
},
{
"name": "Sign of Odin",
"id": 2,
"description": "A tumultuous child at birth, your muscles bear the strength of Odin himself."
}
]
}
Out of desperation I tried converting a class like this to a json, and it just wrote to the file "{ }". When I try to do the same with just my StarSignData class it works as expected, but I need to put multiple objects in my json and the list class does not seem to work. I also can't use external libraries such as SimpleJson for this.

Update property in json file with C#

I'm looking to change a specific property for each json record in my json file. I'd like to change the "Completed" property to "true" when a method finishes executing.
My json file looks like:
{
"LoanRecords": [
{
"LoanGUID": "{70dbec7e-5e94-460d-831c-0a5dc2d085e2}",
"RecordDT": "2020-11-10T14:44:34.378Z",
"Completed": "false",
"Environment": "TEBE",
"ProcessType": "RateLock"
},
{
"LoanGUID": "{70dbec7e-5e94-460d-831c-0a5dc2d085e2}",
"RecordDT": "2020-11-10T14:53:12.187Z",
"Completed": "false",
"Environment": "TEBE",
"ProcessType": "RateLock"
}
]
}
My C# code is the following:
private void ExecuteEvent(object sender, ElapsedEventArgs e)
{
string fileRecord = File.ReadAllText(jsonfile);
LoanRecordRoot LoanRecord = JsonConvert.DeserializeObject<LoanRecordRoot>(fileRecord);
foreach (var rec in LoanRecord.LoanRecords)
{
if (rec.Completed == "false")
{
bool recordModified = ManipulateEncompass(rec.LoanGUID, rec.ProcessType);
if (recordModified)
{
// What should I do here to update "rec.Completed" to "true"
// for this particular record and write it back to the json file
// for that specific entry?
}
}
}
Console.WriteLine("Successfully manipulated records!");
}
Is there a way to flip the "Completed" property to "true" for the specific record in my "foreach" iteration, and update the json file accordingly for that specific record? I am hoping to avoid reading the entire file, deserializing, changing the property then writing the entire content back to the json file, I'm looking to just flip that specific property for each record in my "foreach" loop. -- I hope that makes sense.
I've looked at similar questions, which seem close to what I'm looking for, but the examples I've seen don't reflect writing back to the json file specifically without overwriting the file contents -- unless this specific action isn't possible, or I'm failing to understand the entire process (highly possible.)
Ex of a solution that's close to what I'm looking for: How to update a property of a JSON object using NewtonSoft -- but doesn't seem to quite fit the bill for what I'm wanting to do.
Thank you in advance for any helpful leads!
you need to save the complete JSON when you update a property of an element of the array
static void Main(string[] args)
{
const string jsonPath = #"C:\Logs\recordRoot.json";
var loanRecordRoot = JsonConvert.DeserializeObject<LoanRecordRoot>(File.ReadAllText(jsonPath));
foreach (var record in loanRecordRoot.LoanRecords)
{
if (record.Completed == "false")
{
if (ManipulateEncompass(rec.LoanGUID, rec.ProcessType))
{
record.Completed = "true";
}
}
}
//Save Json
var json = JsonConvert.SerializeObject(loanRecordRoot, Formatting.Indented);
File.WriteAllText(jsonPath, json);
}
Looking at your JSON, it appears the "Completed" property is being serialized as of type string
Therefore, all you need to do is set it to "Completed": "true" within your condition in your snippet.
if (recordModified)
{
rec.Completed = "true";
}
At the end of your processing, simply serialize your LoanRecord object and write it back to your file.
using Kitchen_Mini_Project.Constants;
using Kitchen_Mini_Project.Moduls;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Kitchen_Mini_Project.Services
{
public class Update
{
public static void UpdateAnyProduct()
{
string readdedFile = File.ReadAllText(PathConst.ProductDBPath);
IList<Restaurant> products = JsonConvert.DeserializeObject<IList<Restaurant>>(readdedFile);
foreach (var product in products[0].FoodItems)
{
if (product.foodName == "Chicken Burrito")
{
product.foodName = "Chicken Burrito is Update ha ha";
}
}
var json = JsonConvert.SerializeObject(products, Formatting.Indented);
File.WriteAllText(PathConst.ProductDBPath, json);
}
}
}
1-install package Newtonsoft.Json
https://learn.microsoft.com/en-us/nuget/consume-packages/install-use-packages-visual-studio
2-use
string json = File.ReadAllText("server_client _input.json");
dynamic jsonObj = Newtonsoft.Json.JsonConvert.DeserializeObject(json);
jsonObj["Bots"][0]["Password"] = "new password";
string output = Newtonsoft.Json.JsonConvert.SerializeObject(jsonObj, Newtonsoft.Json.Formatting.Indented);
File.WriteAllText("settings.json", output);
(For Install package use of this page :https://www.newtonsoft.com/json)

Transfer values between 2 config files

I have a problem, and i can't figure this out myself..
In my program i have an auto updater, when my program updates a new(changed, some new keys) config file is created. what i want my program to do is, is when it's updating to look at both config files(old and new) and transfer old settings that match a key in the new file to the new file.
This is an example of the old file:
{
"Setting1": false,
"Setting2": 123,
"Setting3": "test",
"LocationList": {
"Country": "NL",
"Locations": [
{
"Latitude": 38.556807486461118,
"Longitude": -121.2383794784546
},
{
"Latitude": -33.859019,
"Longitude": 151.213098
},
{
"Latitude": 47.5014969,
"Longitude": -122.0959568
},
{
"Latitude": 51.5025343,
"Longitude": -0.2055027
}
]
}
}
And this can be the new file(can also be different):
{
"Setting1": null,
"Setting2": null,
"Setting3": "",
"Setting4": ""
"LocationList": {
"Country": "",
"Locations": [
{
"Latitude": null,
"Longitude": null
},
{
"Latitude": null,
"Longitude": null
}
]
}
}
Expected result:
{
"Setting1": false,
"Setting2": 123,
"Setting3": "test",
"Setting4": ""
"LocationList": {
"Country": "NL",
"Locations": [
{
"Latitude": 38.556807486461118,
"Longitude": -121.2383794784546
},
{
"Latitude": -33.859019,
"Longitude": 151.213098
},
{
"Latitude": 47.5014969,
"Longitude": -122.0959568
},
{
"Latitude": 51.5025343,
"Longitude": -0.2055027
}
]
}
}
First, i looked at creating a class in c# and just deserialize it, then, i came to the conclusion that this is not possible because i don't know what the config is going to look like.
Second, i thought using a dynamic would do the trick, it didn't, because i didn't knew any keys that were in it. And couldn't figure out how to figure that out.
And lastly, i've looked if it would be possible using regex, for me, this seems impossible..
Can anybody give me some ideas of how they would do it? I don't need code, just a push in the right direction.
P.S. i do not want to combine the two, when there is a key in the old file but not in the new one, it doesn't need to be transferred(Only lists will be completely transferred from the old file, also when the list is empty/filled in the new one).
If you really want to try something in JSON, I can only recommend the excellent JSON.Net library to parse the json for you. Using LINQ to JSON you could easily find matching keys in a recursive fashion between the old config file and the newer one and simply copy the value from one to the other
see documentation and a small example at http://www.newtonsoft.com/json/help/html/LINQtoJSON.htm
briefly you could do so in pseudoCode. Obviously this would not be super performant because you would recursively walk two files a lot of times and could be optimized, but at the same time unless your configuration files are monstrous blobs this should not pose any problem on any kind of modern hardware
//load both config files
//load the first token in original file and walk recursively
//for each token try to match in the new file and write data if required using the same recursive technique to walk the other file
I don't need code, just a push in the right direction.
Store your configuration in a regular App.config file and leverage the System.Configuration. Depending on the configuration complexity you can either use the ready <appSettings> or construct your own config section(s) and elements. It still be easier and error proof than doing custom config.
The matter is too complicated to start inventing the wheel just to use another (text) format. Even if you solve your current problem, there will be more, which are already solved somewhere within the System.Configration...
You can start exploring the configuration options here; anyways a regular search in your favorite search engine will do the trick...
Oke after some trouble i've managed to fix it(Thanks #Louis).
This is how i've done it:
private static bool TransferConfig(string baseDir, ISession session)
{
//if (!session.LogicSettings.TransferConfigAndAuthOnUpdate)
// return false;
var configDir = Path.Combine(baseDir, "Config");
if (!Directory.Exists(configDir))
return false;
var oldConf = GetJObject(Path.Combine(configDir, "config.json.old"));
var oldAuth = GetJObject(Path.Combine(configDir, "auth.json.old"));
GlobalSettings.Load("");
var newConf = GetJObject(Path.Combine(configDir, "config.json"));
var newAuth = GetJObject(Path.Combine(configDir, "auth.json"));
TransferJSON(oldConf, newConf);
TransferJSON(oldAuth, newAuth);
File.WriteAllText(Path.Combine(configDir, "config.json"), newConf.ToString());
File.WriteAllText(Path.Combine(configDir, "auth.json"), newAuth.ToString());
return true;
}
private static JObject GetJObject(string filePath)
{
return JObject.Parse(File.ReadAllText(filePath));
}
private static bool TransferJSON(JObject oldFile, JObject newFile)
{
try
{
foreach (var newProperty in newFile.Properties())
foreach (var oldProperty in oldFile.Properties())
if (newProperty.Name.Equals(oldProperty.Name))
{
newFile[newProperty.Name] = oldProperty.Value;
break;
}
return true;
}
catch
{
return false;
}
}

How to set permissions to public, Elastic Transcoder Amazon SDK

How I can make all files public using Amazon.ElasticTranscoder.Model (.NET, C#).
Here is my code:
public static void CreateJobRequest(string videoPath, string bucketName)
{
string accsessKey = CloudSettings.AccessKeyID;
string secretKey = CloudSettings.SecreteKey;
var etsClient = new AmazonElasticTranscoderClient(accsessKey,secretKey, RegionEndpoint.USEast1);
var notifications = new Notifications()
{
Completed = "arn:aws:sns:us-east-1:XXXXXXXXXXXX:Transcode",
Error = "arn:aws:sns:us-east-1:XXXXXXXXXXXX:Transcode",
Progressing = "arn:aws:sns:us-east-1:XXXXXXXXXXXX:Transcode",
Warning = "arn:aws:sns:us-east-1:XXXXXXXXXXXX:Transcode"
};
var pipeline=etsClient.CreatePipeline(new CreatePipelineRequest()
{
Name = "MyFolder",
InputBucket = bucketName,
OutputBucket = bucketName,
Notifications = notifications,
Role = "arn:aws:iam::XXXXXXXXXXXX:role/Elastic_Transcoder_Default_Role"
}).CreatePipelineResult.Pipeline;
etsClient.CreateJob(new CreateJobRequest()
{
PipelineId = pipeline.Id,
Input = new JobInput()
{
AspectRatio = "auto",
Container = "mp4",
FrameRate = "auto",
Interlaced = "auto",
Resolution = "auto",
Key = videoPath
},
Output = new CreateJobOutput()
{
ThumbnailPattern = videoPath+"videoName{resolution}_{count}",
Rotate = "0",
PresetId = "1351620000000-000020",
Key = videoPath+"newFileName.mp4"
}
});
}
Everything works perfect, but transcoded files are private. How I can set it to public?
I've just had this issue today and the way to resolve it is as follows:
In your Pipeline under "Configure Amazon S3 Bucket for Transcoded Files and Playlists"
Use the "+ Add a permission link".
Select "Grantee Type" as "Amazon S3 Group".
Select "Grantee" as "All Users".
Then check "Access" as "Open/Download" AND "View Permission"
Save changes.
You can repeat this for any thumbnails that are generated in the section directly beneath: "Configure Amazon S3 Bucket for Thumbnails".
Just to add to #timstermatic answer - I only had to grant 'Open/Download' access to make the objects public.
The 'View Permissions' option is used to allow anyone to read the ACL (Access Control List) of the object, not to view the object itself - that's taken care of by the 'Open/Download' option.
As usual with AWS terms, it's easy to misinterpret - it's not 'Permission to View the Object', it's 'View the Object's Permissions'.
(Sorry I couldn't add this as a comment, I don't have enough rep.)
Usually a conflict in policies can give rise to this situation. An easier way to handle this is to set the public read permission straight on the bucket in the "Bucket Policy" section of the Permissions tab. This bit of code might help.
{
"Version": "2008-10-17",
"Statement": [
{
"Sid": "AllowPublicRead",
"Effect": "Allow",
"Principal": {
"AWS": "*"
},
"Action": "s3:GetObject",
"Resource": "arn:aws:s3:::<BUCKET_NAME>/*"
}
]
}
You can specify the folder as well in the Resource parameter. Haven't tried extensions but I guess those should work too.

How to concatenate JObects

I have a couple JObjects that are being returned from different places but that have all the same properties. I need to concatenate/merge this into one larger jObject. Is this possible and how would I go about doing it?
I want it to have all the same proerties as the individual objects. For instance.
jObject1 = { "data": [{"name": "foo","id": "1234" }]};
jObject2 = {"data": [{ "name": "foo2", "id": "5678" }]};
Resulting in something like this.
jobject3 = { "data": [{ "name": "foo", "id": "1234"}, { "name": "foo2", "id": "5678" }]};
I'm coding in C# and the only thing I have thought about doing so far is something like this which isn't valid. Not really sure how to begin and can't really anything.
jobject3 = jObject1.Concat(jObject2);
I am trying to manually loop through each object and build a new object. I think I am close but keep getting an error when adding the second item (oAlldepartment.Add) saying "Can not add property to Newtonsoft.Json.Linq.JObject. Property with the same name already exists on object.".
dynamic dynObj = JsonConvert.DeserializeObject(people);
foreach (var item in dynObj.data)
{
string id = item.id;
string name = item.name;
department = getdepartment(id);
JObject oDepartment = new JObject();
try
{
if (!String.IsNullOrEmpty(department))
oDepartment = JObject.Parse(department);
}
catch (Exception ex)
{
}
JArray departmentArray = new JArray();
if (oDepartment != null)
{
foreach (var x in oDepartment["data"].Children())
{
try
{
JObject departmentObject = new JObject();
((JObject)departmentObject).Add(new JProperty("name", x["name"]));
((JObject)departmentObject).Add(new JProperty("department", new JObject(new JProperty("name", x["department"]["name"]))));
((JObject)departmentObject).Add(new JProperty("hire_date", x["hire_date"]));
((JObject)departmentObject).Add(new JProperty("description", x["description"]));
departmentArray.Add(departmentObject);
}
catch (Exception ex)
{
}
((JObject)x).Add(new JProperty("itemtype", "post"));
}
try
{
oAlldepartment.Add(new JProperty("", new JArray(departmentArray)));
}
catch (Exception ex)
{
}
}
}
Thanks,
Rhonda
What I ended up doing was creating a class that defined the json I wanted to return and adding the json properties from each indivual object. The other benefit is my data returned by the method to the client is cleaner as I only have to worry about the properties I need instead of a huge json object with a bunch of properties that I don't need.
Rhonda

Categories

Resources