Mapster icon indicating copy to clipboard operation
Mapster copied to clipboard

Google.Protobuf.WellKnownTypes.Timestamp Error while compiling

Open npatersontemenos opened this issue 1 year ago • 5 comments

Using GRPC, the proto class that maps to my POCO has one field of type google.protobuf.Timestamp, whereas, it is a datetime field in my poco. The error says "source=Google.Protobuf.WellKnownTypes.Timestamp destination=System.DateTime" and goes onto say: "Cannot convert immutable type, please consider using 'MapWith' method to create mapping". I assume this means in the configure RegisterMappings method? Can anyone steer me in the right direction to resolve this please? My code is similar to: TypeAdapterConfig<W1, W2>.NewConfig() .Map(dest => dest.dt, src => src.Dt1)

npatersontemenos avatar Jun 17 '24 20:06 npatersontemenos

public class MapsterConfiguration : IRegister
{
    public void Register(TypeAdapterConfig config)
    {
        config.ForType<Timestamp, DateTime>().MapWith(d => d.ToDateTime());
        config.ForType<DateTime, Timestamp>().MapWith(d => Timestamp.FromDateTime(d));
    }
}

stagep avatar Jun 23 '24 00:06 stagep

@stagep Many thanks!

npatersontemenos avatar Jun 24 '24 16:06 npatersontemenos

public class MapsterConfiguration : IRegister
{
    public void Register(TypeAdapterConfig config)
    {
        config.ForType<Timestamp, DateTime>().MapWith(d => d.ToDateTime());
        config.ForType<DateTime, Timestamp>().MapWith(d => Timestamp.FromDateTime(d));
    }
}

how to make the same, but with nullable datetime? because using nullable datetime throws the same error which described in topic

Exzept1on avatar Jul 10 '24 12:07 Exzept1on

If DateTime is nullable then you have 2 options. Use a nullable Timestamp or create your own gRPC message that can handle the nullability of DateTime with a IsNull property. I use this approach.

config.ForType<Timestamp?, DateTime?>().MapWith(d => d == null ? null : d.ToDateTime());
config.ForType<DateTime?, Timestamp?>().MapWith(d => d.HasValue ? Timestamp.FromDateTime(d.Value) : null);

nullable_date_time.proto:

message NullableDateTimeMessage
{
	int32 year = 1;
	int32 month = 2;
	int32 day = 3;
	int32 hour = 4;
	int32 minute = 5;
	int32 second = 6;
	bool is_null = 7;
}

and the mapping

config.ForType<NullableDateTimeMessage, DateTime?>().MapWith(d => d.IsNull ? null : new DateTime(d.Year, d.Month, d.Day, d.Hour, d.Minute, d.Second);
config.ForType<DateTime?, NullableDateTimeMessage>().MapWith(d => d.HasValue ?
            new NullableDateTimeMessage { Year = d.Value.Year, Month = d.Value.Month, Day = d.Value.Day, Hour = d.Value.Hour, Minute = d.Value.Minute, Second = d.Value.Second } :
            new NullableDateTimeMessage { IsNull = true });

stagep avatar Jul 10 '24 14:07 stagep

Thanks for answer.

config.ForType<Timestamp?, DateTime?>().MapWith(d => d == null ? null : d.ToDateTime());

config.ForType<DateTime?, Timestamp?>().MapWith(d => d.HasValue ? DateTime.SpecifyKind(d.Value, DateTimeKind.Utc).ToTimestamp() : null);

This code works for me.

Exzept1on avatar Jul 11 '24 06:07 Exzept1on