{"record":{"id":"a1454ed3a24281c8","repo":"XINCGer/Unity3DTraining","slug":"expected-object-value-for-struct","errorCode":null,"errorMessage":"Expected object value for Struct","messagePattern":"Expected object value for Struct","errorType":"validation","errorClass":"InvalidProtocolBufferException","httpStatus":null,"severity":"error","filePath":"NetWorkAndResources/Socket_Protobuff/Assets/Plugins/Google.Protobuf/JsonParser.cs","lineNumber":474,"sourceCode":"                    {\n                        var field = fields[Value.ListValueFieldNumber];\n                        var list = NewMessageForField(field);\n                        tokenizer.PushBack(firstToken);\n                        Merge(list, tokenizer);\n                        field.Accessor.SetValue(message, list);\n                        return;\n                    }\n                default:\n                    throw new InvalidOperationException(\"Unexpected token type: \" + firstToken.Type);\n            }\n        }\n\n        private void MergeStruct(IMessage message, JsonTokenizer tokenizer)\n        {\n            var token = tokenizer.Next();\n            if (token.Type != JsonToken.TokenType.StartObject)\n            {\n                throw new InvalidProtocolBufferException(\"Expected object value for Struct\");\n            }\n            tokenizer.PushBack(token);\n\n            var field = message.Descriptor.Fields[Struct.FieldsFieldNumber];\n            MergeMapField(message, field, tokenizer);\n        }\n\n        private void MergeAny(IMessage message, JsonTokenizer tokenizer)\n        {\n            // Record the token stream until we see the @type property. At that point, we can take the value, consult\n            // the type registry for the relevant message, and replay the stream, omitting the @type property.\n            var tokens = new List<JsonToken>();\n\n            var token = tokenizer.Next();\n            if (token.Type != JsonToken.TokenType.StartObject)\n            {\n                throw new InvalidProtocolBufferException(\"Expected object value for Any\");\n            }","sourceCodeStart":456,"sourceCodeEnd":492,"githubUrl":"https://github.com/XINCGer/Unity3DTraining/blob/016f98412ea5e11756b286736f479b66ab6216d5/NetWorkAndResources/Socket_Protobuff/Assets/Plugins/Google.Protobuf/JsonParser.cs#L456-L492","documentation":"google.protobuf.Struct's canonical JSON form is a plain JSON object. MergeStruct reads the first token and, if it is not StartObject, throws this InvalidProtocolBufferException. Struct is internally stored as a map<string, Value>, so its JSON must be an object of field names to arbitrary values.","triggerScenarios":"Calling JsonParser.Parse where a google.protobuf.Struct field receives a JSON array, string, number, boolean, or null instead of an object, e.g. {\"metadata\": [1,2,3]}.","commonSituations":"Sending arrays or scalars to a Struct field that semantically should be an object; Confusion between google.protobuf.Value (accepts anything) and google.protobuf.Struct (object only); APIs that stringify metadata before parsing.","solutions":["Change the JSON so the Struct field is a JSON object: \"metadata\": {\"k\": \"v\"}.","If arbitrary (non-object) values are intended, change the schema to use google.protobuf.Value for that field instead of Struct.","Wrap scalar/array payloads in an object before parsing, e.g. {\"items\": [...]}.","Catch InvalidProtocolBufferException around Parse and return guidance that Struct fields require JSON objects."],"exampleFix":"// before: Struct given an array\n{\"metadata\": [\"a\", \"b\"]}\n\n// after\n{\"metadata\": {\"a\": 1, \"b\": 2}}","handlingStrategy":"validation","validationCode":"// Struct fields must be JSON objects\nfunction validateStructField(payload, name) {\n  const v = payload[name];\n  if (v !== undefined && (typeof v !== 'object' || v === null || Array.isArray(v))) {\n    throw new Error(`${name} (google.protobuf.Struct) must be a JSON object`);\n  }\n}","typeGuard":"function isStructLike(v) { return v !== null && typeof v === 'object' && !Array.isArray(v); }","tryCatchPattern":"try { var msg = JsonParser.Default.Parse<T>(json); }\ncatch (InvalidProtocolBufferException ex) when (ex.Message == \"Expected object value for Struct\") { /* return 400: Struct field requires JSON object */ }","preventionTips":["Remember Struct = object only; use google.protobuf.Value when any JSON value is allowed","Validate metadata fields as objects at API ingress","Unit-test payload builders that target Struct fields"],"tags":["protobuf","json-parsing","struct","well-known-type"],"backgroundTag":"protobuf-unmarshal-failed","analyzedSha":"016f98412ea5e11756b286736f479b66ab6216d5","analyzedAt":"2026-09-12T01:08:58.711Z","contentChangedAt":"2026-09-12T01:08:58.711Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}