MapsterMapper / MapsterMapper/Mapster
Flattening ignores explicit type mapping rules
A pull request for this has already been merged.
- #981 by @DocSvartz — merged
- Dominant language
- C#
- Stars
- 5.2k
- Forks
- 410
- Avg merge
- 2d 12h
- Merged PRs (30d)
- 6
Description
Setup
I have an Entity object with Props collection.
class Entity
{
public string Name { get; set; } = default!;
public List<EntityProp> Props { get; set; } = default!;
}
class EntityProp
{
public string Key { get; set; } = default!;
public string Value { get; set; } = default!;
}
My goal is to map it into a Dto object where items from Props collections become properties of destination object.
class Dto
{
public string Name { get; set; } = default!;
public string? Address { get; set; }
public string? Description { get; set; }
public string? Phone { get; set; }
}
For versatility I have two mapping. First is to flatten the Props into destination root and second to configure Props mapping.
config.NewConfig<Entity, Dto>().Map(e => e, e => e.Props);
config.NewConfig<List<EntityProp>, Dto>()
.Map(e => e.Address, e => e.Get("Address"))
.Map(e => e.Description, e => e.Get("Description"))
.Map(e => e.Phone, e => e.Get("Phone"));
Problem
Second mapping rules are not obeyed during conversion. Is this pattern valid? Any workaround?
Complete code sample
using System.Collections.Generic;
using System.Linq;
using Mapster;
class Entity
{
public string Name { get; set; } = default!;
public List<EntityProp> Props { get; set; } = default!;
}
class EntityProp
{
public string Key { get; set; } = default!;
public string Value { get; set; } = default!;
}
class Dto
{
public string Name { get; set; } = default!;
public string? Address { get; set; }
public string? Description { get; set; }
public string? Phone { get; set; }
}
static class TestMapster
{
public static void Test()
{
TypeAdapterConfig config = new();
config.NewConfig<Entity, Dto>().Map(e => e, e => e.Props);
config.NewConfig<List<EntityProp>, Dto>()
.Map(e => e.Address, e => e.Get("Address"))
.Map(e => e.Description, e => e.Get("Description"))
.Map(e => e.Phone, e => e.Get("Phone"));
Entity ent = new()
{
Name = "My entity",
Props = [
new() { Key = "Phone", Value = "12345678" }
],
};
Dto dto = ent.Adapt<Dto>(config);
// dto.Name is mapped correctly and equals to "My entity".
// Expected dto.Phone to be equal to "12345678",
// but it is not mapped and is null
}
}
static class ListExtensions
{
// utility method as expression bodies are not allowed to have null propagating operator
public static string? Get(this List<EntityProp> list, string key)
=> list.FirstOrDefault(e => e.Key == key)?.Value;
}
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with the complete C# sample, especially the two NewConfig calls and the Entity.Adapt(config) entry point. Verify the expected Phone value against the observed null result; done means the explicit List to Dto mapping is honored during flattening, with the behavior reconciled with merged PR #981.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- backend
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100