Offer a flag for exact numeric conversions
Ninguém assumiu esta issue ainda.
Avaliação
- Dificuldade
- 5/5
- Tempo estimado
- Mais de uma semana
- Facilidade para iniciantes
- 35/100
Direção de pesquisa
Comece examinando o comportamento existente de typeConversionPolicy e as conversões numéricas geradas descritas na issue, incluindo BigDecimal-to-Integer e outras conversões potencialmente com perda. Defina como um sinalizador precisionLossStrategy seria aplicado a todas essas conversões, preservando IGNORE como padrão. O trabalho estará concluído quando o modo estrito produzir conversões sem perda ou o comportamento de falha especificado, sem exigir métodos personalizados por campo.
Escrita pelo modelo de indexação a partir do texto da issue.
Descrição
Use case
As of now, numeric conversions like BigDecimal to Integer use BigDecimal.intValue(), which is a narrowing conversions, discard fractional part and may overflow. My applications, and probably from many others, would benefit from a more strict behavior, like that provided by BigDecimal.intValueExact().
That should be applicable for all potentially lossy conversions (double-to-int, long-to-int, etc), potentially even for cases like converting a timestamp with nanosecond precision into a datatype format that only goes up to millisecond.
I think an ideal solution would be a new flag for configuring behavior, like mapstruct.precisionLossStrategy with values like IGNORE and ERROR, with IGNORE as default to ensure backwards compatibility for existing code.
Example code with current behavior:
@Mapper
public interface MyMapper {
MyMapper INSTANCE = Mappers.getMapper(MyMapper.class);
IntegerRecord map(BigDecimalRecord value);
BigDecimalRecord map(IntegerRecord value);
record BigDecimalRecord(BigDecimal number) {}
record IntegerRecord(Integer number) {}
static void main(String[] args) {
System.out.println(INSTANCE.map(new BigDecimalRecord(new BigDecimal("1.9"))));
}
}
Output:
IntegerRecord[value=1]
Desired output:
java.lang.ArithmeticException: Rounding necessary
Generated Code
Currently generated code:
@Override
public MyMapper.IntegerRecord map(MyMapper.BigDecimalRecord bigDecimalRecord) {
// ...
if ( bigDecimalRecord.number() != null ) {
number = bigDecimalRecord.number().intValue();
}
// ...
}
Desired generated code:
@Override
public MyMapper.IntegerRecord map(MyMapper.BigDecimalRecord bigDecimalRecord) {
// ...
if ( bigDecimalRecord.number() != null ) {
number = bigDecimalRecord.number().intValueExact();
}
// ...
}
Possible workarounds
The current alternatives I see now:
- using
qualifiedByNamewith a custom method to ensure lossless conversion- but that easily gets overwhelming if dealing with lots of numeric field mappings
- moreover, one need to manually apply it to every field pair, and that makes missing some a very likely scenario
- using
typeConversionPolicy=ERRORand providing manual conversion methods for all required conversions- less error prone, but still requires setting the flag everywhere or importing a shared config everywhere (mistake opportunities), plus all the boilerplate code that could be provided by MapStruct
If there is a better way to achieve the described behavior, I'd be glad to know.
MapStruct Version
1.6.3
- Linguagem predominante
- Java
- Estrelas
- 7.7k
- Forks
- 1.1k
- Métricas de merge de PRs
- Nenhum PR com merge em 30d
Guia de contribuição
Primeiros passos
- Leia a issue inteira e depois o guia de contribuição do projeto.
- Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
- Faça um fork do repositório e trabalhe em uma branch.
- Abra um pull request que referencie o número da issue.
Mais de mapstruct/mapstruct
-
bug test
Dificuldade 4/5 3-5 dias Facilidade para iniciantes 48/100
-
bug
Dificuldade 3/5 1-2 dias Facilidade para iniciantes 68/100
-
Dificuldade 4/5 3-5 dias Facilidade para iniciantes 68/100
-
bug JSpecify
-
Dificuldade 3/5 1-2 dias Facilidade para iniciantes 72/100
Todas as issues de mapstruct/mapstruct
Issues semelhantes
-
executions.Query — startDate and timeRange filters are sent with inverted comparison operators Abertaarea/plugin
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 75/100
kestra-io/plugin-kestra#190 ·
-
litertlm-android AAR ships no consumer ProGuard rules → "mid == null" SIGABRT in minified apps Aberta
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 70/100
google-ai-edge/LiteRT-LM#3739 ·
-
bug
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 75/100
-
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 75/100
integra-team-red/meet-map#249 ·
-
[Studio][Bug] Cancelled create-user dialog keeps the password and admin switch for the next attempt Aberta
Dificuldade 2/5 1-3 horas Facilidade para iniciantes 75/100
apache/rocketmq-dashboard#5064 ·