Question:
What is the best way to pull JSON from a .json file on my server, into code, so it can be deserialized into a .NET object?
Details:
I have a file called "backlog.json" saved in my VS2013 Express MVC project. The file was not created by my project - it has been added to the project by doing "Add Existing Item."
"backlog.json" is a collection of json objects. I need to pull these objects from the collection, so I can add to the database my project uses and manipulate with my project.
The project uses .NET Framework 4.5, and I've added NewtonSoft's Json.NET to the project, using NuGet package manager. Once I get the objects from "backlog.json" into my code, I'll use Json.NET to deserialize and manipulate the objects through C#.
For example, something like:
public void AddJSON(EFWorkOrderModelContainer WorkOrderContainer)
{
// Pull backlog.json from C:\Project\App_Data\backlog.json
// De-serialize and parse
}
You can't do string myjson = File.ReadAllText("~/App_Data/backlog.json"); because File class doesn't know how to convert from an application root relative path. You can do string myjson = File.ReadAllText(Server.MapPath("~/App_Data/backlog.json")); or if Server isn't in scope string myjson = File.ReadAllText(HttpContext.Current.Server.MapPath("~/App_Data/backlog.json"));
You should not do string json = File.ReadAllText(#"C:\Project\App_Data\backlog.json"); because that's dependent on where you place the website within your web server, and that's a bad idea.
Yes, MSDN is down right now, so you can't use that to look up the namespace for the File class. But in Visual Studio, if you just type File you can use Intellisense to have it automatically import the namespace for you by right-clicking the File.
I won't mark my own answer as "answered," but a similar way of going about this is actually described on Newtonsoft.com's site. Click here to see the sample... it describes exactly what I was looking for.
Related
As mentioned in this other question, I'm setting my first steps in C# and JSON.
I'm working on a small application, that can read information from a DB and write it in a JSON file. In order to do this, I thought of creating the classes as they were defined in the JSON file. For that, I used Web Essentials and this has done a great job: the classes are generated completely. All this is mentioned in my previous question.
Now I was thinking of using those classes to write back to the JSON file, so I have this situation:
JSON file1 : used as an input in order to create the class diagram.
DB : contains some information I need to add to the JSON file.
JSON file2 : used as an output, based on "JSON file1", and having the
extra information, retrieved from the DB.
Very naïvely apparently, I've done this:
root.ToString(); // hoping that this would generate the JSON output.
But, I only seem to get some basic information out of that method (namespace and classname, no content).
Using intellisense, I don't see any method which generates my JSON output, but there's one flair of hope in my code (the one, generated by Web Essentials), as you can see:
public class Rootobject
{
public Project project { get; set; }
}
public class Project
{
public string commonDESCRIPTION { get; set; }
...
public Location[] locations { get; set; }
As you can see, neither Rootobject or Project inherit from anything (nor do they realise an interface), and I just cannot believe there isn't any class which covers this behaviour. So, I would like to know from which class I need to inherit in order to solve this issue.
I, however, don't think it might be that easy, and maybe some Web Essentials configuration editing needs to be done in order to cover this, but I don't know how to modify Visual Studio extension configuration.
Edit
Some more information on my Web Essentials installation: after having installed Web Essentials on my Visual Studio 2017 Enterprise platform, I can see Paste Special, Paste JSON as classes in my Edit menu, but I don't see Web Essentials in the menu toolbar (just File, Edit, ...) and in Tools, Options I also don't see any Web Essentials references.
Can anybody help me?
Thanks in advance
Apparently (as mentioned by Ruan), Web Essentials can turn a JSON file into a class model, but in the other direction, another way must be followed.
The way, which is mentioned (NewtonSoft), is a very good one:
Add "NewtonSoft" as a reference (I did it, using the NuGet package Manager).
At the beginning of the source code, add using Newtonsoft.Json;.
The conversion to JSON is simple: string result = JsonConvert.SerializeObject(root);.
I want to add help/documentation text to a library that I am building in C#. I am using /// to create the tags and this works just fine when I use methods of my library in my lirary proyect. For example:
if my library have 2 classes Car and Person, if a I type in Person
Car.StartEngi
the auto complete of VS will suggest to use StartEngine methos and I will see the summary that for the method, fro example "This method will start the engine of the car".
But the issue comes when I compile and try to reference the dll on a separate solution. In the new solution I have already add the corresponding reference and using statement but when I write
Car.StartEngi
VS will indeed recommend to use StartEngine BUT I can not see the documentation. Does anyone know why? Do I need to add some parameter when I build the library?
P.D All the methods in the library that generates the dll are public
On the Build page of your project settings you need to turn on "XML documentation file". If you copy the XML documentation file along with your assembly then you should be able to see the documentation in other projects.
I'm currently designing a cross-plateform application in Visual Studio 2013 using a Portable Class Library.
At startup, I want to have a certain object, created by deserializing a JSON file. This object will be used to configure certain resources in my project (e.g. certain button names, etc.).
I know how to parse the JSON file using Json.NET and to create the wanted object.
What I don't know is how to use it, and especially, where must it be generated? I don't think this JSON reading part could (and should) be added to the PCL, for the file reading part at least.
Thanks in advance (I hope this isn't a duplicate!)
In a separate project I have a de-serialized xml file with strings that I want to use in my WPF application, these strings are also used within a different project in the same solution, so I can't just move the strings over to the project holding the wpf application.
The program is structured like this:
Project A references B and C
WPF application with event handlers
Project B references C
GUI logic in F#
Project C
XML resource file and de-serializer (written in F#)
Is there a way for me to make a resource or resource dictionary based on the objects from the deserialized xml file? or can I reference the strings stored in the xml file directly?
I would suggest you to use the built-in .resx file, which is included by default in freshly created WPF application. (You can also add it at later time using Project -> Add New Item... -> Resource File.) Just be sure to set the access modifier to "Public" and you will be able to use the strings inside other projects that references the current one:
You will be able to access strings (and other resources as well!) through a strongly-typed, automatically generated wrapper class:
MessageBox.Show(WpfApplication1.Properties.Resources.String1);
You can also set properties using XAML to the strings stored in this file, using the x:Static markup extension, as desribed in (for example) this answer:
xmlns:resx="clr-namespace:WpfApplication1.Properties;assembly=WpfApplication1"
Title="{x:Static resx:Resources.String1}"
Additionally you'll get nice, Visual Studio built-in, UI for editing the file (also visible in the picture).
From what it seems your projects that will use the common resource strings will be implemented using WPF technology. In this case you could change a little the format of your xml and have directly a xaml file containing the serialized form of a ResourceDictionary. After that you can just deserialize your file and you have a ResourceDictionary. Serialization and deserialization can be done using the XamlWriter and XamlReader.
Code example:
var pc = new ParserContext
{
BaseUri = new Uri(runtimeResourcesDirectory , UriKind.Absolute)
};
...
using (Stream s = File.Open(resourceDictionaryFile, FileMode.Open, FileAccess.Read))
{
try
{
var resourceDictionary = XamlReader.Load(s, pc) as ResourceDictionary;
if (resourceDictionary != null)
{
Resources.MergedDictionaries.Add(resourceDictionary);
}
}
catch
{
MessageBox.Show("Invalid xaml: " + resourceDictionaryFile);
}
}
}
The tooling in F# project is not so good, so what I have suggested in my previous answer won't work.
In C# projects, there is custom tool named "ResXFileCodeGenerator" that is run (just before the build) over the .resx file and generates the C# wrapper class. This is obviosly not available in F# projects. You have to workarounds though.
The easiest approach that comes to my mind - that is if you want to use the strongly typed wrapper generated from the C# custom tool - is to add new C# class library to your solution, which will contain the resx file and will generate the wrapper class. You can add the .resx file from Project -> Add New Item... -> Resource File. Then you can reference this library from all your F# projects and use the generated wrapper class:
open ClassLibrary1; // this is the C# library
...
let x = Resources.String1;
The second approach is to add a .resx file directly to your F# project. The funny thing here is that Visual Studio won't allow you to "Add new item" of type Resource. You can workaround this by creating Resource file in another, temporary project - for example of type C# class library, and then add the generated .resx file to your F# project using the Project -> Add Existing Item command. Then you can use the resources from the resx file using the ResourceManager class (of course without the generated properties for every resources, as in the previous case):
open Library1
open System.Resources
[<EntryPoint>]
let main argv =
// We are in the console application, which references Library1
// Library1 contains the .resx file.
let resourceManager = ResourceManager("Resources", typeof<Library1.Class1>.Assembly);
let x = resourceManager.GetString("String1");
0
Note that in the upper case I have added the resource file directly in the project (not in subfloder), as a file named Resources.resx.
You can additionally create your custom wrapper which encapsulates such calls within properties.
Turns out I managed to do something that works like I intended, but instead of using the deserialized objects, I used the xml file itself.
Here's what I did:
First I changed the XML file's Build Action from Content to Resource by going Right-click the file -> Properties -> Build Action -> Resource
Then I went into the Xaml file, and added the following to Window.Resources
<XmlDataProvider
x:Key="DropDownData"
Source="/Resource;component/Strings.xml"
XPath="/Strings/String" />
In the drop-down menu that I needed the strings I added this:
ItemsSource="{Binding Source={StaticResource DropDownData}}"
And now my strings are beautifully displayed in the WPF gui.
Thanks for your suggestions though; they may come in useful in the future.
What is the advantage of adding XML files to a visual studio 2008 project (windows form app project for example).
Once added to the project, how could I refer to this XML to use it in a class in the same project? In this case, I would be sending it as a query to a web service.
If you want to use the XML in some form, you could mark it as a "embedded resource" in the properties window, and then access it from your code like so:
Assembly a = Assembly.GetExecutingAssembly();
if(a != null)
{
Stream s = a.GetManifestResourceStream(typeof(yourType), "YourXmlName.xml");
if (s != null)
{
String xmlContents = new StreamReader(s).ReadToEnd();
}
}
Once you're done, you have the XML file's contents in "xmlContents", if all goes well.
Marc
I guess the advantage of having your XML reside there in your project (or solution even) is that you can maintain it in VS with nice formatting and even intelli-sense, but then using something like XML Spy or whatever can give you that too.
To refer to it in a class you'll need to ensure you have access to it, and that it resides in a reliable place.
In the past I've used post build events to move the latest copy of the file to where I need it. As Arnshea writes here is another answer, "to the output directory". You can use the "Copy to Output directory" property on the XML file itself to achieve this. Then your classes can use the XML file, knowing it will reside in a reliable place.
You'll need to make sure it's accessible though especially if you're writing back to it. Make sure it doesn't end up "Read Only" - as Source Control system could do to you. Storing these files in a folder under Program Files could also be problematic especially on Vista, where user privileges are (should be) restricted.
If your app needs to load the XML it can be copied to the output directory. Also simplifies use of Setup/Deployment projects...
Another major advantage would be (assuming it's in place--and it should be!) is that you can apply revision control to the XML file.
I guess that you won't be sending the same XML file to the WebService over and over again.
You will want to modify its content every time for that you have XML Serialization.
If all of the above apply then you don't need the XML file, you just need the class that generates the file at runtime. The XML is just the transport, today its XML and tomorrow it might be some other format (JSON).