-1

I have a program in .Net 5 C# that make a HTTP Request and the content (JSON) is deserialized (JsonNewtonsoft) in specific type:

// Class definition
public class FooSerializerModel {

    [JsonProperty("latitude")] 
    public string Latitude { get; set; }

    [JsonProperty("longitude")]
    public string Longitude { get; set; }

}

// Deserialization
var fooJson = JsonConvert.DeserializeObject<FooSerializerModel>(response);

It works fine, now, I need cast the fooJson variable type to other type for pass it to Data Layer Method:

public class DataModel {

    public string Latitude { get; set; }

    public string Longitude { get; set; }

}

I need something like this:

var data = fromJson as DataModel;

But I get this error: Cannot convert type FooSerializerModel to DataModel Why?

I know is possible solve this problem using:

var data = new DataModel() {
    Latitude = fromJson.Latitude,
    Longitude = fromJson.Longitude
}

But if my class has 50 attributes I would have to assign one by one, it would be more lines of code and I could forget some of them when doing it explicitly.

Is it possible to do an implicit assignment on a single line? I have tried this:

var data = fromJson as DataModel; // Error

var data = (DataModel) fromJson; // Error

var data = (DataModel) (object) fromJson; // Exception 'Unable to cast object of type' when use 'dotnet run'

I remember that it is possible to do this in TypeScript if you work with types with interfaces and is easy!

Serge
  • 40,935
  • 4
  • 18
  • 45
Julián
  • 1,238
  • 1
  • 12
  • 24
  • 1
    `Why?` - because they are completely unrelated types? – GSerg Oct 16 '21 at 23:18
  • 1
    Does this answer your question? [How to convert a class object to an other class type with similar properties?](https://stackoverflow.com/questions/44638967/how-to-convert-a-class-object-to-an-other-class-type-with-similar-properties) – GSerg Oct 16 '21 at 23:21
  • 1
    Does this answer your question? [Cast objects of different classes but same types](https://stackoverflow.com/q/855283/11683) – GSerg Oct 16 '21 at 23:23
  • Why use a SerializerModel in the first place. Why not just deserialize into DataModel from the get go, adding the attributes required? – Frontear Oct 16 '21 at 23:24
  • @GSerg The first question uses AutoMapper, which appears to be a package, it seems to answer my question, but I would like to know if there is a more native or natural way to solve the problem without a Nuget package, otherwise I am forced to close the question – Julián Oct 16 '21 at 23:47
  • @GSerg The second link brings me to the idea of using `JsonConvert.DeserializeObject(JsonConvert.SerializeObject (fooJson));` but I see that some attributes are assigned null and it is a strange way to do it – Julián Oct 16 '21 at 23:49
  • @Frontear Because DataModel is a class for operations with MongoDB (Data Context) otherwise I would have used deserialization with DataModel class, In addition, the JSON that returns me has lowercase attributes and forces me to use JsonProperty, it is for this reason that I try to separate responsibilities and use two classes – Julián Oct 16 '21 at 23:50
  • You probably want to rework your design for a variety of reasons but, literally, given `class DataModel { public int P { get; set; } }` and `class ViewModel { public int P { get; set; } public static explicit operator DataModel(ViewModel vm) => new DataModel { P = vm.P }; }` one may write `var vm = new ViewModel { P = 42 }; var dm = (DataModel)vm;` Thus, the language can express what you're asking for. – Aluan Haddad Oct 17 '21 at 06:27
  • @AluanHaddad It is an interesting way to solve it, but it leads to explicitly assigning each attribute, I think the most successful way is the idea that GSerg has given me to use JsonConvert, it has worked for me with a small variation in my real case – Julián Oct 17 '21 at 15:22

1 Answers1

1

All the code was tested in Visual Studio and working properly.

var fooJson = JsonConvert.DeserializeObject<DataModel>(response);

everything will be fine, since you don't really need [JsonProperty] attribute. You just need to fix your startup or there are another options to conver low case to upper.

public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews()
    .AddNewtonsoftJson(options =>
           options.SerializerSettings.ContractResolver =
              new CamelCasePropertyNamesContractResolver());

     .... other code
}

but I even don't think that json attributes will affect your classes even if you use them for MongoDB. Classes are classes, but attributes are attributes, they live a completely separate life.

Another very popular way is to use AutoMapper

using AutoMapper;

.......

var mapper = new Mapper(new MapperConfiguration(x => x.AddProfile(new AutoMapperProfiles())));

DataModel data = mapper.Map<DataModel>(fooJson);


public class AutoMapperProfiles : Profile
{
    public AutoMapperProfiles()
    {

        CreateMap<FooSerializerModel, DataModel>();
    }
}

But if you like it hard way I can offer this

public class DataModel 
{

    public virtual string Latitude { get; set; }

    public virtual string Longitude { get; set; }

}

public class FooSerializerModel:DataModel
{

    [JsonProperty("latitude")]
    public override string Latitude { get; set; }

    [JsonProperty("longitude")]
    public override string Longitude { get; set; }

}

Now you can write the code you wanted

var fooJson = JsonConvert.DeserializeObject<FooSerializerModel>(response);
DataModel data=fooJson;
Serge
  • 40,935
  • 4
  • 18
  • 45
  • Hi Serge, this solution is not valid for me... Because DataModel is a class for operations with MongoDB (Data Context) otherwise I would have used deserialization with DataModel class, In addition, the JSON that returns me has lowercase attributes and forces me to use JsonProperty, it is for this reason that I try to separate responsibilities and use two classes – Julián Oct 16 '21 at 23:43