Newtonsoft.Json icon indicating copy to clipboard operation
Newtonsoft.Json copied to clipboard

Trimming support

Open HavenDV opened this issue 1 year ago • 3 comments

When trying to publish an application with <PublishTrimmed>true</PublishTrimmed>, this library produces the following:

  Newtonsoft.Json.dll: [IL2104] Assembly 'Newtonsoft.Json' produced trim warnings. For more information see https://aka.ms/dotnet-illink/libraries

I guess it doesn't support net6.0/net7.0 trimming - https://aka.ms/dotnet-illink/libraries

HavenDV avatar Feb 09 '23 10:02 HavenDV

Any feature-rich reflection-based serializer or library (like Newtonsoft.Json/Json.NET) is a struggle regarding trimming.

As the documentation you linked to states:

Sometimes the existing design of an API will render it mostly trim-incompatible, and you may need to find other ways to accomplish what it is doing. A common example is reflection-based serializers. In these cases, consider adopting other technology like source generators to produce code that is more easily statically analyzed.

However, all is not lost. If you want to keep using Newtonsoft.Json while keeping trimming enabled, you will have to exclude any of the types (or their assemblies) that your application can potentially (de)serialize through Newtwonsoft.Json from trimming: https://learn.microsoft.com/en-us/dotnet/core/deploying/trimming/trimming-options (But probably it is a good idea to first think about whether migration to System.Text.Json is feasible for you, which would save you from this particular trimming problem.)

elgonzo avatar Feb 09 '23 14:02 elgonzo

I guess in order to eliminate this warning, we need to include <IsTrimmable>true</IsTrimmable> but specify one of the properties:

  • <TrimMode>copyused</TrimMode> Enable assembly-level trimming, which keeps an entire assembly if any part of it is used (in a statically understood way). - https://learn.microsoft.com/en-us/dotnet/core/deploying/trimming/trimming-options?pivots=dotnet-6-0#trimming-granularity
  • <TrimmerRootAssembly Include="Newtonsoft.Json" /> If an assembly is not trimmed it is considered "rooted", which means that it and all of its statically understood dependencies will be kept. Additional assemblies may be "rooted" by name - https://learn.microsoft.com/en-us/dotnet/core/deploying/trimming/trimming-options?pivots=dotnet-6-0#root-assemblies

But I'm not sure if this will set any metadata for this to be distributed via the NuGet package

HavenDV avatar Feb 09 '23 17:02 HavenDV

An easy fix would be to add [DynamicDependency(...)] on one of key methods (which is called no matter what - e.g. one of type initializers) to make sure every type needed for JSON deserialization stays in place even with <TrimMode>full</TrimMode>.

Right now Newtonsoft.JSON doesn't work when fully trimmed, and it seems in our specific case it's the only library in this state now.

alexyakunin avatar Nov 23 '23 10:11 alexyakunin