diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md
index 9b24b75040c..e88e696600e 100644
--- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md
+++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/CHANGELOG.md
@@ -15,6 +15,9 @@ option
   can still be used with .NET5.0 apps.
   ([#3147](https://github.com/open-telemetry/opentelemetry-dotnet/issues/3147))
 
+* Fix handling of array-valued attributes for the OTLP trace exporter.
+  ([#3238](https://github.com/open-telemetry/opentelemetry-dotnet/pull/3238))
+
 ## 1.3.0-beta.1
 
 Released 2022-Apr-15
diff --git a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/ActivityExtensions.cs b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/ActivityExtensions.cs
index d5ef774889e..fbc123db6b7 100644
--- a/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/ActivityExtensions.cs
+++ b/src/OpenTelemetry.Exporter.OpenTelemetryProtocol/Implementation/ActivityExtensions.cs
@@ -396,6 +396,8 @@ public bool ForEach(KeyValuePair<string, object> activityTag)
                     this.Created = true;
                 }
 
+                OtlpCommon.ArrayValue arrayValue;
+
                 switch (activityTag.Value)
                 {
                     case string s:
@@ -416,39 +418,49 @@ public bool ForEach(KeyValuePair<string, object> activityTag)
                         PooledList<OtlpCommon.KeyValue>.Add(ref this.Tags, CreateOtlpKeyValue(key, new OtlpCommon.AnyValue { DoubleValue = d }));
                         break;
                     case int[] intArray:
+                        arrayValue = new OtlpCommon.ArrayValue();
                         foreach (var item in intArray)
                         {
-                            PooledList<OtlpCommon.KeyValue>.Add(ref this.Tags, CreateOtlpKeyValue(key, new OtlpCommon.AnyValue { IntValue = item }));
+                            arrayValue.Values.Add(new OtlpCommon.AnyValue { IntValue = item });
                         }
 
+                        PooledList<OtlpCommon.KeyValue>.Add(ref this.Tags, CreateOtlpKeyValue(key, new OtlpCommon.AnyValue { ArrayValue = arrayValue }));
                         break;
                     case double[] doubleArray:
+                        arrayValue = new OtlpCommon.ArrayValue();
                         foreach (var item in doubleArray)
                         {
-                            PooledList<OtlpCommon.KeyValue>.Add(ref this.Tags, CreateOtlpKeyValue(key, new OtlpCommon.AnyValue { DoubleValue = item }));
+                            arrayValue.Values.Add(new OtlpCommon.AnyValue { DoubleValue = item });
                         }
 
+                        PooledList<OtlpCommon.KeyValue>.Add(ref this.Tags, CreateOtlpKeyValue(key, new OtlpCommon.AnyValue { ArrayValue = arrayValue }));
                         break;
                     case bool[] boolArray:
+                        arrayValue = new OtlpCommon.ArrayValue();
                         foreach (var item in boolArray)
                         {
-                            PooledList<OtlpCommon.KeyValue>.Add(ref this.Tags, CreateOtlpKeyValue(key, new OtlpCommon.AnyValue { BoolValue = item }));
+                            arrayValue.Values.Add(new OtlpCommon.AnyValue { BoolValue = item });
                         }
 
+                        PooledList<OtlpCommon.KeyValue>.Add(ref this.Tags, CreateOtlpKeyValue(key, new OtlpCommon.AnyValue { ArrayValue = arrayValue }));
                         break;
                     case string[] stringArray:
+                        arrayValue = new OtlpCommon.ArrayValue();
                         foreach (var item in stringArray)
                         {
-                            PooledList<OtlpCommon.KeyValue>.Add(ref this.Tags, CreateOtlpKeyValue(key, item == null ? null : new OtlpCommon.AnyValue { StringValue = item }));
+                            arrayValue.Values.Add(item == null ? new OtlpCommon.AnyValue() : new OtlpCommon.AnyValue { StringValue = item });
                         }
 
+                        PooledList<OtlpCommon.KeyValue>.Add(ref this.Tags, CreateOtlpKeyValue(key, new OtlpCommon.AnyValue { ArrayValue = arrayValue }));
                         break;
                     case long[] longArray:
+                        arrayValue = new OtlpCommon.ArrayValue();
                         foreach (var item in longArray)
                         {
-                            PooledList<OtlpCommon.KeyValue>.Add(ref this.Tags, CreateOtlpKeyValue(key, new OtlpCommon.AnyValue { IntValue = item }));
+                            arrayValue.Values.Add(new OtlpCommon.AnyValue { IntValue = item });
                         }
 
+                        PooledList<OtlpCommon.KeyValue>.Add(ref this.Tags, CreateOtlpKeyValue(key, new OtlpCommon.AnyValue { ArrayValue = arrayValue }));
                         break;
                     default:
                         PooledList<OtlpCommon.KeyValue>.Add(ref this.Tags, CreateOtlpKeyValue(key, new OtlpCommon.AnyValue { StringValue = activityTag.Value.ToString() }));
diff --git a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpTestHelpers.cs b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpTestHelpers.cs
index 7b0da3aeee2..0cb994bbeb0 100644
--- a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpTestHelpers.cs
+++ b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpTestHelpers.cs
@@ -33,58 +33,56 @@ public static void AssertOtlpAttributes(
             for (int i = 0; i < expectedAttributes.Count; i++)
             {
                 var current = expectedAttributes[i].Value;
+                Assert.Equal(expectedAttributes[i].Key, actual[i].Key);
 
                 if (current.GetType().IsArray)
                 {
+                    Assert.Equal(OtlpCommon.AnyValue.ValueOneofCase.ArrayValue, actual[i].Value.ValueCase);
                     if (current is bool[] boolArray)
                     {
-                        int index = 0;
-                        foreach (var item in boolArray)
+                        Assert.Equal(boolArray.Length, actual[i].Value.ArrayValue.Values.Count);
+                        for (var j = 0; j < boolArray.Length; ++j)
                         {
-                            Assert.Equal(expectedAttributes[i].Key, actual[i + index].Key);
-                            AssertOtlpAttributeValue(item, actual[i + index]);
-                            index++;
-                            expectedSize++;
+                            AssertOtlpAttributeValue(boolArray[j], actual[i].Value.ArrayValue.Values[j]);
                         }
+
+                        expectedSize++;
                     }
                     else if (current is int[] intArray)
                     {
-                        int index = 1;
-                        foreach (var item in intArray)
+                        Assert.Equal(intArray.Length, actual[i].Value.ArrayValue.Values.Count);
+                        for (var j = 0; j < intArray.Length; ++j)
                         {
-                            Assert.Equal(expectedAttributes[i].Key, actual[i + index].Key);
-                            AssertOtlpAttributeValue(item, actual[i + index]);
-                            index++;
-                            expectedSize++;
+                            AssertOtlpAttributeValue(intArray[j], actual[i].Value.ArrayValue.Values[j]);
                         }
+
+                        expectedSize++;
                     }
                     else if (current is double[] doubleArray)
                     {
-                        int index = 2;
-                        foreach (var item in doubleArray)
+                        Assert.Equal(doubleArray.Length, actual[i].Value.ArrayValue.Values.Count);
+                        for (var j = 0; j < doubleArray.Length; ++j)
                         {
-                            Assert.Equal(expectedAttributes[i].Key, actual[i + index].Key);
-                            AssertOtlpAttributeValue(item, actual[i + index]);
-                            index++;
-                            expectedSize++;
+                            AssertOtlpAttributeValue(doubleArray[j], actual[i].Value.ArrayValue.Values[j]);
                         }
+
+                        expectedSize++;
                     }
                     else if (current is string[] stringArray)
                     {
-                        int index = 3;
-                        foreach (var item in stringArray)
+                        Assert.Equal(stringArray.Length, actual[i].Value.ArrayValue.Values.Count);
+                        for (var j = 0; j < stringArray.Length; ++j)
                         {
-                            Assert.Equal(expectedAttributes[i].Key, actual[i + index].Key);
-                            AssertOtlpAttributeValue(item, actual[i + index]);
-                            index++;
-                            expectedSize++;
+                            AssertOtlpAttributeValue(stringArray[j], actual[i].Value.ArrayValue.Values[j]);
                         }
+
+                        expectedSize++;
                     }
                 }
                 else
                 {
                     Assert.Equal(expectedAttributes[i].Key, actual[i].Key);
-                    AssertOtlpAttributeValue(current, actual[i]);
+                    AssertOtlpAttributeValue(current, actual[i].Value);
                     expectedSize++;
                 }
             }
@@ -92,27 +90,27 @@ public static void AssertOtlpAttributes(
             Assert.Equal(expectedSize, actual.Count);
         }
 
-        private static void AssertOtlpAttributeValue(object expected, OtlpCommon.KeyValue actual)
+        private static void AssertOtlpAttributeValue(object expected, OtlpCommon.AnyValue actual)
         {
             switch (expected)
             {
                 case string s:
-                    Assert.Equal(s, actual.Value.StringValue);
+                    Assert.Equal(s, actual.StringValue);
                     break;
                 case bool b:
-                    Assert.Equal(b, actual.Value.BoolValue);
+                    Assert.Equal(b, actual.BoolValue);
                     break;
                 case long l:
-                    Assert.Equal(l, actual.Value.IntValue);
+                    Assert.Equal(l, actual.IntValue);
                     break;
                 case double d:
-                    Assert.Equal(d, actual.Value.DoubleValue);
+                    Assert.Equal(d, actual.DoubleValue);
                     break;
                 case int i:
-                    Assert.Equal(i, actual.Value.IntValue);
+                    Assert.Equal(i, actual.IntValue);
                     break;
                 default:
-                    Assert.Equal(expected.ToString(), actual.Value.StringValue);
+                    Assert.Equal(expected.ToString(), actual.StringValue);
                     break;
             }
         }
diff --git a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpTraceExporterTests.cs b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpTraceExporterTests.cs
index 33062c9c930..202b1212d55 100644
--- a/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpTraceExporterTests.cs
+++ b/test/OpenTelemetry.Exporter.OpenTelemetryProtocol.Tests/OtlpTraceExporterTests.cs
@@ -333,13 +333,12 @@ public void ToOtlpSpanActivitiesWithNullArrayTest()
 
             Assert.NotNull(otlpSpan);
 
-            var stringArray = otlpSpan.Attributes.Where(kvp => kvp.Key == "stringArray").ToList();
+            var stringArray = otlpSpan.Attributes.FirstOrDefault(kvp => kvp.Key == "stringArray");
 
             Assert.NotNull(stringArray);
-            Assert.Equal(3, stringArray.Count);
-            Assert.Equal("test", stringArray[0].Value.StringValue);
-            Assert.Equal(string.Empty, stringArray[1].Value.StringValue);
-            Assert.Null(stringArray[2].Value);
+            Assert.Equal("test", stringArray.Value.ArrayValue.Values[0].StringValue);
+            Assert.Equal(string.Empty, stringArray.Value.ArrayValue.Values[1].StringValue);
+            Assert.Equal(OtlpCommon.AnyValue.ValueOneofCase.None, stringArray.Value.ArrayValue.Values[2].ValueCase);
         }
 
         [Theory]