What NuGet Provides
NuGet is the package manager for .NET. It lets you add third-party libraries (and Microsoft libraries that ship as packages) to your project in a repeatable way. A NuGet package typically contains compiled assemblies, metadata (package id, version, dependencies), and sometimes extra build assets (analyzers, MSBuild targets).
When you reference a package, your project records that dependency (including its version). During restore/build, NuGet resolves the full dependency graph (your direct packages plus their dependencies) and makes the assemblies available to the compiler and runtime.
Responsible Use of Third-Party Libraries
- Prefer well-maintained packages with clear documentation and active releases.
- Minimize dependencies: add packages only when they provide clear value.
- Review licensing and security posture (known vulnerabilities, maintenance status).
- Pin versions intentionally and update regularly, especially for security fixes.
Adding Packages with dotnet add package
To add a NuGet package to a console app, use the .NET CLI from the project folder (where the .csproj file is located). In this chapter’s example, you will use System.Text.Json for JSON serialization. It is a widely used JSON library in .NET and is distributed as a NuGet package (even though it is also part of many .NET shared frameworks).
Step-by-step: Add the package
dotnet add package System.Text.JsonThis command updates your project file by adding a PackageReference. You can open the .csproj to see something like:
<ItemGroup> <PackageReference Include="System.Text.Json" Version="8.0.0" /></ItemGroup>The exact version may differ depending on your SDK and what NuGet resolves.
Continue in our app.
You can listen to the audiobook with the screen off, receive a free certificate for this course, and also have access to 5,000 other free online courses.
Or continue reading below...Download the app
Restoring Dependencies
Restore is the process of downloading packages and resolving the dependency graph. Many CLI commands implicitly restore (such as dotnet build and dotnet run), but it is useful to know the explicit command.
Step-by-step: Restore
dotnet restoreRestore uses the package references in your project file to download packages into the global NuGet cache. It also generates a lock of resolved versions for the build (recorded in assets files under obj), ensuring your compiler sees the correct assemblies.
If restore fails, common causes include network issues, an invalid package id/version, or a restricted package source configuration.
Referencing Package APIs in Code
After adding a package, you can use its namespaces and types in your code. In practice, that means adding using directives and calling APIs as you would with any other library.
For JSON serialization with System.Text.Json, the main entry point is JsonSerializer in the System.Text.Json namespace.
Hands-on Example: Serialize to JSON, Save to a File, Read and Deserialize
This example creates a small data model, serializes it to JSON, writes it to a file, then reads it back and deserializes it into an object. The goal is to practice the full workflow: add package, restore, reference the API, and use it for a real task.
1) Create a simple model
Add a model type that represents something you might store locally, such as app settings or a user profile.
public class UserProfile{ public string UserName { get; set; } = ""; public int HighScore { get; set; } public string[] FavoriteTags { get; set; } = Array.Empty<string>();}2) Serialize the model to JSON
Create an instance and serialize it. Use JsonSerializerOptions to make the output readable (indented). In real apps, you might also configure naming policies or converters.
using System.Text.Json;public class Program{ public static void Main() { var profile = new UserProfile { UserName = "alex", HighScore = 4200, FavoriteTags = new[] { "console", "csharp", "json" } }; var options = new JsonSerializerOptions { WriteIndented = true }; string json = JsonSerializer.Serialize(profile, options); Console.WriteLine(json); }}3) Save the JSON to a file
Pick a file path (for example, in the current working directory) and write the JSON string.
using System.Text.Json;public class Program{ public static void Main() { var profile = new UserProfile { UserName = "alex", HighScore = 4200, FavoriteTags = new[] { "console", "csharp", "json" } }; var options = new JsonSerializerOptions { WriteIndented = true }; string json = JsonSerializer.Serialize(profile, options); string filePath = "userprofile.json"; File.WriteAllText(filePath, json); Console.WriteLine($"Saved JSON to {filePath}"); }}4) Read the file and deserialize back into an object
Read the JSON text and deserialize it into UserProfile. The generic overload Deserialize<T> is the most common approach.
using System.Text.Json;public class Program{ public static void Main() { string filePath = "userprofile.json"; string jsonFromFile = File.ReadAllText(filePath); UserProfile? loaded = JsonSerializer.Deserialize<UserProfile>(jsonFromFile); if (loaded is null) { Console.WriteLine("Failed to load profile."); return; } Console.WriteLine("Loaded profile:"); Console.WriteLine($"UserName: {loaded.UserName}"); Console.WriteLine($"HighScore: {loaded.HighScore}"); Console.WriteLine($"Tags: {string.Join(", ", loaded.FavoriteTags)}"); }}5) Put it together as a single runnable program
This combined version writes the file and then reads it back in the same run, which is convenient for testing.
using System.Text.Json;public class UserProfile{ public string UserName { get; set; } = ""; public int HighScore { get; set; } public string[] FavoriteTags { get; set; } = Array.Empty<string>();}public class Program{ public static void Main() { var profile = new UserProfile { UserName = "alex", HighScore = 4200, FavoriteTags = new[] { "console", "csharp", "json" } }; var options = new JsonSerializerOptions { WriteIndented = true }; string filePath = "userprofile.json"; string json = JsonSerializer.Serialize(profile, options); File.WriteAllText(filePath, json); string jsonFromFile = File.ReadAllText(filePath); UserProfile? loaded = JsonSerializer.Deserialize<UserProfile>(jsonFromFile); if (loaded is null) { Console.WriteLine("Failed to deserialize JSON into UserProfile."); return; } Console.WriteLine($"Loaded {loaded.UserName} with score {loaded.HighScore}."); }}If you get a deserialization result of null, it usually means the JSON is empty, malformed, or does not match the expected shape. Another common issue is mismatched property names when using custom naming policies.
Dependency Considerations: Versioning and Documentation
Versioning basics
NuGet packages use versions like Major.Minor.Patch. As a rule of thumb:
- Patch updates should be backward compatible and include bug fixes.
- Minor updates typically add features but should remain backward compatible.
- Major updates may include breaking changes and require code updates.
You can specify a version when adding a package:
dotnet add package System.Text.Json --version 8.0.0When you update packages, test your app after changes. Even “safe” updates can introduce behavior differences (for example, changes in default serialization behavior or stricter parsing).
Finding package documentation
- Check the package page on NuGet.org for the README, release notes, and repository link.
- Follow the repository link (often GitHub) for detailed docs, samples, and issue tracking.
- Use the API reference (Microsoft Learn for BCL packages like
System.Text.Json, or the library’s own docs for third-party packages).