moov-io / iso8583

A golang implementation to marshal and unmarshal iso8583 message.
https://moov.io
Apache License 2.0
304 stars 100 forks source link

prefix.EBCDIC.Fixed Unpack auto trim #223

Closed xianyongjie closed 1 year ago

xianyongjie commented 1 year ago
spec := &iso8583.MessageSpec{
    Fields: map[int]field.Field{
        30: field.NewString(&field.Spec{
            Length:      24,
            Description: "Amounts, Original",
            Enc:         encoding.EBCDIC,
            Pref:        prefix.EBCDIC.Fixed,
            Pad:         padding.Left('0'),
        }),
    },
}

for Pack and Unpack ,I use the same spec.but Unpack will auto trim.Is there any options that can set unpack not to trim?

alovak commented 1 year ago

Unfortunately there is no such option :(

alovak commented 1 year ago

@xianyongjie What your issue is? If you share some more details maybe we can find a solution.

xianyongjie commented 1 year ago

spec := &iso8583.MessageSpec{

    Fields: map[int]field.Field{
        0: field.NewString(&field.Spec{
            Length:      4,
            Description: "Message Type Indicator",
            Enc:         encoding.EBCDIC,
            Pref:        prefix.EBCDIC.Fixed,
        }),
        1: field.NewBitmap(&field.Spec{
            Length:      8,
            Description: "Bitmap",
            Enc:         encoding.Binary,
            Pref:        prefix.EBCDIC.Fixed,
        }),
        30: field.NewString(&field.Spec{
            Length:      24,
            Description: "Amounts, Original",
            Enc:         encoding.EBCDIC,
            Pref:        prefix.EBCDIC.Fixed,
            Pad:         padding.Left('0'),
        }),
    },
}
message := iso8583.NewMessage(spec)
message.MTI("0100")
message.Field(30, "000000000000000000001000")
m, _ := message.Pack()

msg1 := iso8583.NewMessage(spec)
err := msg1.Unpack(m)
if err != nil {
    log.Error(err)
}
v, _ := msg1.GetString(30)
log.Info(v)

I want 000000000000000000001000,but print 1000

alovak commented 1 year ago

@xianyongjie here is the explanation of the issue. In the specification on the field 30 you have Pad: padding.Left('0'),.

Let's see how it works when we pack messages. If you set value of amount as 123 when field value will be padded with 0 at the beginning:

000000000000000000000123

That's convenient sometimes.

But when you get the same value in the message and you unpack it, then same 0s will be removed, giving you 123 as a field value.

You said you want 000000000000000000001000 and not 1000, to achieve this you have to remove Pad from the field spec like this:

30: field.NewString(&field.Spec{
            Length:      24,
            Description: "Amounts, Original",
            Enc:         encoding.EBCDIC,
            Pref:        prefix.EBCDIC.Fixed,
        }),

BUT, to not break packing, you will have to manually add 0s when you set field value like this:

value := fmt.Sprintf("%024s", v) // pad with 0 at the beginning, so the total length is 24
Pad:         padding.Left('0'),

does exactly the same - it pads value with 0 at the beginning.

I hope that will solve your issue.

xianyongjie commented 1 year ago

@alovak thanks.but for that I have to define pack spec(that has pad) and unpack spec (that has no pad).

alovak commented 1 year ago

@xianyongjie it's up to you to work with two specs (but I don't recommend such an option as you have to keep both in sync which may be problematic). Here is what I advise you either

  1. use field spec with Pad: padding.Left('0') and when you unpack - just pad zeroes yourself with fmt.Sprintf("%024s", val) to get 000000000000000000001000 or
  2. remove Pad: padding.Left('0') from the field spec and before setting value to the field and packing, pad it with zeroes using fmt.Sprintf("%024s", val).

both options are solutions for either packing or unpacking.

xianyongjie commented 1 year ago

@alovak the above example has one pad field ,but actual spaec has more pad field。so I have to define two specs.

alovak commented 1 year ago

If you decide to work with https://github.com/moov-io/iso8583-connection then having two specs will not work for you :(