Newtonsoft. Json Сериализация: InvalidCastException - PullRequest
0 голосов
/ 06 августа 2020

У меня есть приложение Xamarin.Forms (4.7.0.1239) и настраиваемая реализация MVVM.

Intro

Каждая ViewModel имеет void OnPageAppearing () и ICommand NextCommand.

public BaseContentPage<TViewModel> : ContentPage 
    where TViewModel : BaseViewModel
{
    public virtual void OnPageAppearing()
    {
        ViewModel.OnPageAppearing(); 
        base.OnPageAppearing();
    }

    // ...
}

public BaseViewModel : INotifyPropertyChanged
{
    public virtual OnPageAppearing() { }
}

Когда я вызываю OnPageAppearing(), я загружаю данные из хранилища (десериализую JSON). Когда я вызываю NextCommand, я сохраняю данные в хранилище (я сериализую для своих моделей).

У меня есть несколько моделей:

public enum ProductAnomaly
{
    Missing,
    Broken
}

public class Anomaly
{
    public string ProductId { get; set; }
    [JsonIgnore]
    public Product Product { get; set; }
    public ProductAnomaly Type { get; set; }
    public string PhotoFileName { get; set; }
    public string Comment { get; set; }
}

public class Product
{
    public string Id { get ; set ; } = Guid.NewGuid().ToString();
    public string Description { get; set; }
    public string Barcode { get; set; }
    public string Barcode2 { get; set; }
    public string MissionId { get; set; }
    public bool IsValidated { get; set; } = true;
    public int DeliveredQuantity { get; set; } = 0;
    public bool? WithMounting { get; set; }
    public int Quantity { get; set; }
    public System.Collections.Generic.HashSet<Anomaly> Anomalies { get; set; }
}

В одной из моих ViewModels я вызываю NextCommand и я сохраняю данные:

// ReportAnomalyViewModel: 

private Product _product;
public Product Product 
{
    get => _product;
    set => SetProperty(ref _product, value);
}

public ICommand NextCommand => new Command(async () => 
{
    await DataService.SaveAnomalyToStorage(Product, ProductAnomaly.Missing);
}
// DataService:
public async Task SaveAnomalyToStorage(Product product, ProductActivity productAnomaly)
{
    var anomaly = new Anomaly 
    {
        Type = productAnomaly,
        Product = product,
        ProductId = product.Id,
        Comment = comment,
        PhotoFileName = photoFileName
    }

    var json = JsonConvert.SerializeObject(anomaly);
    //...
}

... и

[0:] Invoke 'SaveAnomalyToStorageAsync'
08-06 18:57:10.111 I/Choreographer(12422): Skipped 2657 frames!  The application may be doing too much work on its main thread.
08-06 18:57:10.128 I/OpenGLRenderer(12422): Davey! duration=44301ms; Flags=0, IntendedVsync=12648113739375, Vsync=12692397070937, OldestInputEvent=9223372036854775807, NewestInputEvent=0, HandleInputStart=12692398346460, AnimationStart=12692398374460, PerformTraversalsStart=12692398492660, DrawStart=12692408231060, SyncQueued=12692409579560, SyncStart=12692410445760, IssueDrawCommandsStart=12692410615460, SwapBuffers=12692411988260, FrameCompleted=12692415697560, DequeueBufferDuration=248000, QueueBufferDuration=2886000, 
**System.InvalidCastException:** 'Specified cast is not valid.'

Thread finished: <Thread Pool> #12
The thread 0xc has exited with code 0 (0x0).
08-06 18:57:30.089 D/Mono    (12422): DllImport attempting to load: '/system/lib/liblog.so'.
08-06 18:57:30.089 D/Mono    (12422): DllImport loaded library '/system/lib/liblog.so'.
08-06 18:57:30.089 D/Mono    (12422): DllImport searching in: '/system/lib/liblog.so' ('/system/lib/liblog.so').
08-06 18:57:30.089 D/Mono    (12422): Searching for '__android_log_print'.
08-06 18:57:30.089 D/Mono    (12422): Probing '__android_log_print'.
08-06 18:57:30.089 D/Mono    (12422): Found as '__android_log_print'.
08-06 18:57:30.096 I/MonoDroid(12422): UNHANDLED EXCEPTION:
08-06 18:57:30.099 I/MonoDroid(12422): System.InvalidCastException: Specified cast is not valid.
08-06 18:57:30.099 I/MonoDroid(12422):   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue (Newtonsoft.Json.JsonWriter writer, System.Object value, Newtonsoft.Json.Serialization.JsonContract valueContract, Newtonsoft.Json.Serialization.JsonProperty member, Newtonsoft.Json.Serialization.JsonContainerContract containerContract, Newtonsoft.Json.Serialization.JsonProperty containerProperty) [0x000d6] in <2073514815234917a5e8f91b0b239405>:0 
08-06 18:57:30.099 I/MonoDroid(12422):   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize (Newtonsoft.Json.JsonWriter jsonWriter, System.Object value, System.Type objectType) [0x00079] in <2073514815234917a5e8f91b0b239405>:0 
08-06 18:57:30.099 I/MonoDroid(12422):   at Newtonsoft.Json.JsonSerializer.SerializeInternal (Newtonsoft.Json.JsonWriter jsonWriter, System.Object value, System.Type objectType) [0x0023a] in <2073514815234917a5e8f91b0b239405>:0 
08-06 18:57:30.099 I/MonoDroid(12422):   at Newtonsoft.Json.JsonSerializer.Serialize (Newtonsoft.Json.JsonWriter jsonWriter, System.Object value, System.Type objectType) [0x00000] in <2073514815234917a5e8f91b0b239405>:0 
08-06 18:57:30.099 I/MonoDroid(12422):   at Newtonsoft.Json.JsonConvert.SerializeObjectInternal (System.Object value, System.Type type, Newtonsoft.Json.JsonSerializer jsonSerializer) [0x00028] in <2073514815234917a5e8f91b0b239405>:0 
08-06 18:57:30.099 I/MonoDroid(12422):   at Newtonsoft.Json.JsonConvert.SerializeObject (System.Object value, System.Type type, Newtonsoft.Json.JsonSerializerSettings settings) [0x00007] in <2073514815234917a5e8f91b0b239405>:0 
08-06 18:57:30.099 I/MonoDroid(12422):   at Newtonsoft.Json.JsonConvert.SerializeObject (System.Object value) [0x00000] in <2073514815234917a5e8f91b0b239405>:0 
08-06 18:57:30.099 I/MonoDroid(12422):   at Abc.Mobile.Services.DataService.SaveAnomalyToStorageAsync (Abc.Entities.Product product, Abc.Entities.ProductAnomaly productAnomaly, System.String comment, System.String photoFileName) [0x0006e] in C:\Repos\Abc\src\Abc.Mobile\Services\DataService.cs:326 
08-06 18:57:30.099 I/MonoDroid(12422):   at Abc.Mobile.ViewModels.ReportAnomalyViewModel.<get_NextCommand>b__35_0 () [0x0022e] in C:\Repos\Abc\src\Abc.Mobile\ViewModels\ReportAnomalyViewModel.cs:100 
08-06 18:57:30.099 I/MonoDroid(12422):   at System.Runtime.CompilerServices.AsyncMethodBuilderCore+<>c.<ThrowAsync>b__7_0 (System.Object state) [0x00000] in /Users/builder/jenkins/workspace/archive-mono/2020-02/android/release/mcs/class/referencesource/mscorlib/system/runtime/compilerservices/AsyncMethodBuilder.cs:1021 
08-06 18:57:30.099 I/MonoDroid(12422):   at Android.App.SyncContext+<>c__DisplayClass2_0.<Post>b__0 () [0x00000] in <eaa205f580954a64824b74a79fa87c62>:0 
08-06 18:57:30.099 I/MonoDroid(12422):   at Java.Lang.Thread+RunnableImplementor.Run () [0x00008] in <eaa205f580954a64824b74a79fa87c62>:0 
08-06 18:57:30.099 I/MonoDroid(12422):   at Java.Lang.IRunnableInvoker.n_Run (System.IntPtr jnienv, System.IntPtr native__this) [0x00008] in <eaa205f580954a64824b74a79fa87c62>:0 
08-06 18:57:30.099 I/MonoDroid(12422):   at (wrapper dynamic-method) Android.Runtime.DynamicMethodNameCounter.1(intptr,intptr)

пытается

dotnetfiddle

Я пробовал тот же код здесь: https://dotnetfiddle.net/wjlMdW

Работает ...

Другой проект

Мой объект аномалии правильно сериализуется ...

в другом консольном проекте (do tnet core), я сослался на свои модели и попробовал:

static void Main(string[] args)
{
    var product = new Product
    {
        Anomalies = new System.Collections.Generic.HashSet<Anomaly>(),
        Barcode = Guid.NewGuid().ToString(),
        Barcode2 = Guid.NewGuid().ToString(),
        DeliveredQuantity = 0,
        Description = Guid.NewGuid().ToString(),
        MissionId = Guid.NewGuid().ToString(),
        Quantity = 3,
        WithMounting = false
    };

    var anomaly = new Anomaly
    {
        Type = ProductAnomaly.Missing,
        Product = product,
        ProductId = product.Id,
        Comment = "",
        PhotoFileName = ""
    };

    var json = JsonConvert.SerializeObject(anomaly);
    System.Console.WriteLine(json);
    System.Console.ReadLine();
}

Результат:

Unhandled exception. System.InvalidCastException: Unable to cast object of type 'Abc.Entities.Anomaly' to type 'System.Collections.IEnumerable'.
   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.SerializeValue(JsonWriter writer, Object value, JsonContract valueContract, JsonProperty member, JsonContainerContract containerContract, JsonProperty containerProperty)
   at Newtonsoft.Json.Serialization.JsonSerializerInternalWriter.Serialize(JsonWriter jsonWriter, Object value, Type objectType)
   at Newtonsoft.Json.JsonSerializer.SerializeInternal(JsonWriter jsonWriter, Object value, Type objectType)
   at Newtonsoft.Json.JsonSerializer.Serialize(JsonWriter jsonWriter, Object value, Type objectType)
   at Newtonsoft.Json.JsonConvert.SerializeObjectInternal(Object value, Type type, JsonSerializer jsonSerializer)
   at Newtonsoft.Json.JsonConvert.SerializeObject(Object value, Type type, JsonSerializerSettings settings)
   at Newtonsoft.Json.JsonConvert.SerializeObject(Object value)
   at Abc.Console.Program.Main(String[] args) in C:\Repos\Abc\src\Abc.Console\Program.cs:line 33
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...