Hi Florian, Thanks for your quick response. I'm stuck on this.
1) It's not working. When I send the protobuf to the backend server (it's not our api nor server) using the first method, I get a right response. But using the second method I receive this error: ProtoBuf.ProtoException: Invalid wire-type; this usually means you have over-written a file without truncating or setting the length; see https://stackoverflow.com/q/2152978/23354 at ProtoBuf.ProtoReader.StartSubItem(ProtoReader reader) in C:\code\protobuf-net\src\protobuf-net\ProtoReader.cs:line 637 at ProtoBuf.ProtoReader.ReadTypedObject(Object value, Int32 key, ProtoReader reader, Type type) in C:\code\protobuf-net\src\protobuf-net\ProtoReader.cs:line 584 at proto_40(Object , ProtoReader ) at ProtoBuf.Meta.TypeModel.DeserializeCore(ProtoReader reader, Type type, Object value, Boolean noAutoCreate) in C:\code\protobuf-net\src\protobuf-net\Meta\TypeModel.cs:line 722 at ProtoBuf.Meta.TypeModel.Deserialize(Stream source, Object value, Type type, SerializationContext context) in C:\code\protobuf-net\src\protobuf-net\Meta\TypeModel.cs:line 599 at WebBeds.Connect.AspNetCore.Formatters.ProtobufInputFormatter.ReadRequestBodyAsync(InputFormatterContext context) at Microsoft.AspNetCore.Mvc.Formatters.InputFormatter.ReadAsync(InputFormatterContext context) at Microsoft.AspNetCore.Mvc.ModelBinding.Binders.BodyModelBinder.BindModelAsync(ModelBindingContext bindingContext) at Microsoft.AspNetCore.Mvc.ModelBinding.ParameterBinder.BindModelAsync(ActionContext actionContext, IModelBinder modelBinder, IValueProvider valueProvider, ParameterDescriptor parameter, ModelMetadata metadata, Object value, Object container) at Microsoft.AspNetCore.Mvc.Controllers.ControllerBinderDelegateProvider.<>c__DisplayClass0_0.<<CreateBinderDelegate>g__Bind|0>d.MoveNext() --- End of stack trace from previous location --- at Microsoft.AspNetCore.Mvc.Infrastructure.ControllerActionInvoker.<InvokeInnerFilterAsync>g__Awaited|13_0(ControllerActionInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted) at Microsoft.AspNetCore.Mvc.Infrastructure.ResourceInvoker.<InvokeNextExceptionFilterAsync>g__Awaited|26_0(ResourceInvoker invoker, Task lastTask, State next, Scope scope, Object state, Boolean isCompleted 2) This is the proto: The request with the 'Meta' element: message Request { Meta Meta = 1; repeated int32 Hotels = 2 [packed = false]; Country Market = 3; repeated Room Rooms = 4; .bcl.DateTime CheckIn = 5; .bcl.DateTime CheckOut = 6; OptionalCriteria OptionalCriteria = 7; } The 'Meta' element that contains the 'CutOffTime' that we want to modify: message Meta { int32 Client = 1; int32 Brand = 2; bool UseCache = 3; .bcl.TimeSpan CutOffTime = 4; bool B2C = 5; Language Language = 6; Currency Currency = 7; bool IncludeProviderAuditData = 8; SalesChannel SalesChannel = 9; string AgentId = 10; } The 'CutOffTime': message TimeSpan { sint64 value = 1; // the size of the timespan (in units of the selected scale) TimeSpanScale scale = 2; // the scale of the timespan [default = DAYS] enum TimeSpanScale { DAYS = 0; HOURS = 1; MINUTES = 2; SECONDS = 3; MILLISECONDS = 4; TICKS = 5; MINMAX = 15; // dubious } } Thanks, Joan. On Wednesday, September 20, 2023 at 10:40:08 AM UTC+2 Florian Enner wrote: > 1) A "varint" is a "variable length integer". When you replace a large > number with a small one, it's entirely possible to lose some bytes and > still be valid. You need to check the actual output. > > 2) Can you provide the proto definition of the field you want to modify? > Scalar fields get set to the last encountered value, so the easiest option > may be to copy the original bytes and append a delta containing the > differences. > > > > > On Wednesday, September 20, 2023 at 10:19:07 AM UTC+2 Joan Balagueró wrote: > >> Hello, >> >> I have a protobuf message like this into a byte array: >> >> 1: { // META element >> 1: 2 >> 2: 1 >> 3: 1 >> 4: { // CutOffTime element within META >> 1: 10 >> 2: 3 >> } >> 5: 1 >> 6: 40 >> } >> 2: 9836 // HOTEL element >> 3: 724 // MARKET element >> >> >> We need to traverse this message and write it to a 'CodeOutputStream', >> but changing the values of the 'cutoff' element to, for example to '4: { 1: >> 7, 2: 4 }'. I'm not able to do it, I need some help. >> >> A basic algorithm that writes the same protobuf to another byte array but >> without changing anything works. Here I try the special case of 'META' (key >> = 1) that contains the 'cutoff' element. >> >> Map<Integer, UnknownFieldSet.Field> rootFields = >> UnknownFieldSet.parseFrom(document).asMap(); >> >> for (Map.Entry<Integer, UnknownFieldSet.Field> entry : >> rootFields.entrySet()) { >> if (entry.getKey() == 1) { >> ByteString bs = >> entry.getValue().getLengthDelimitedList().get(0); >> output.writeByteArray(1, bs.toByteArray()); >> } >> else { >> entry.getValue().writeTo(entry.getKey(), output); >> } >> } >> >> >> Now I try to go a bit further, trying to read the cuotff element, change >> the values and rewrite them to the 'output'. And here is when I'm not able >> to solve the problem. Below my try that does not work, it generates a byte >> array >> of 69 bytes instead of 73 (I'm losing 4 bytes): >> >> Map<Integer, UnknownFieldSet.Field> rootFields = >> UnknownFieldSet.parseFrom(document).asMap(); >> >> for (Map.Entry<Integer, UnknownFieldSet.Field> entry : >> rootFields.entrySet()) { >> if (entry.getKey() == 1) { >> ByteString bs = >> entry.getValue().getLengthDelimitedList().get(0); >> Map<Integer, UnknownFieldSet.Field> ufs = >> UnknownFieldSet.parseFrom(bs).asMap(); >> >> for (Map.Entry<Integer, UnknownFieldSet.Field> item : >> ufs.entrySet()) { >> if (item.getKey() == 4) { >> Map<Integer, UnknownFieldSet.Field> cutoff = >> UnknownFieldSet.parseFrom(item.getValue().getLengthDelimitedList().get(0)).asMap(); >> cutoff.put(1, >> UnknownFieldSet.Field.newBuilder().addVarint(7).build()).writeTo(1, output); >> cutoff.put(2, >> UnknownFieldSet.Field.newBuilder().addVarint(4).build()).writeTo(1, output); >> } >> else { >> item.getValue().writeTo(item.getKey(), >> output); >> } >> } >> } >> else { >> entry.getValue().writeTo(entry.getKey(), output); >> } >> } >> >> Any help would be really appreciated. >> >> Thanks, >> >> Joan. >> > -- You received this message because you are subscribed to the Google Groups "Protocol Buffers" group. To unsubscribe from this group and stop receiving emails from it, send an email to protobuf+unsubscr...@googlegroups.com. To view this discussion on the web visit https://groups.google.com/d/msgid/protobuf/f72c72ea-47ed-40ee-92b2-42de999b7057n%40googlegroups.com.