How to apply indenting serialization only to some properties?

One possibility would be to write a custom Json converter for the specific types you need special handling and switch the formatting for them:

class Program
{
    static void Main()
    {
        var root = new Root
        {
            Array = new[] { "element 1", "element 2", "element 3" },
            Object = new Obj
            {
                Property1 = "value1",
                Property2 = "value2",
            },
        };
        var settings = new JsonSerializerSettings
        {
            Formatting = Formatting.Indented,
        };
        settings.Converters.Add(new MyConverter());

        string json = JsonConvert.SerializeObject(root, settings);
        Console.WriteLine(json);
    }
}

public class Root
{
    public string[] Array { get; set; }
    public Obj Object { get; set; }
}

public class Obj
{
    public string Property1 { get; set; }
    public string Property2 { get; set; }
}

class MyConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(string[]) || objectType == typeof(Obj);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        writer.WriteRawValue(JsonConvert.SerializeObject(value, Formatting.None));
    }
}

This will output:

{
  "Array": ["element 1","element 2","element 3"],
  "Object": {"Property1":"value1","Property2":"value2"}
}

I also used a converter for this (as per Darin Dimitrov's answer), but instead of calling WriteRawValue() I use the serializer for each element; which ensures any custom converters that apply to the element type will be used.

Note however that this converter is only operating on Arrays of a handful of primitive types, it's not using the Newtonsoft.Json logic for determining what should be serialized as an array and what a primitive type is, basically because that code is internal and I wanted to avoid maintaining a copy of it.

Overall I get the feeling that converters aren't intended to be used for formatting tasks such as this, but I think they're the only option in the current API. Ideally the API would offer a few more formatting options or perhaps better support for custom formatting within the converter API.

using System;
using System.Collections.Generic;
using Newtonsoft.Json;

namespace JsonProto
{
    /// <summary>
    /// A JsonConverter that modifies formatting of arrays, such that the array elements are serialised to a single line instead of one element per line
    /// preceded by indentation whitespace.
    /// This converter handles writing JSON only; CanRead returns false.
    /// </summary>
    /// <remarks>
    /// This converter/formatter applies to arrays only and not other collection types. Ideally we would use the existing logic within Newtonsoft.Json for
    /// identifying collections of items, as this handles a number of special cases (e.g. string implements IEnumerable over the string characters). In order
    /// to avoid duplicating in lots of logic, instead this converter handles only Arrays of a handful of selected primitive types.
    /// </remarks>
    public class ArrayNoFormattingConverter : JsonConverter
    {
        # region Static Fields    

        static HashSet<Type> _primitiveTypeSet = 
            new HashSet<Type> 
            { 
                typeof(char),
                typeof(char?),
                typeof(bool),
                typeof(bool?),
                typeof(sbyte),
                typeof(sbyte?),
                typeof(short),
                typeof(short?),
                typeof(ushort),
                typeof(ushort?),
                typeof(int),
                typeof(int?),
                typeof(byte),
                typeof(byte?),
                typeof(uint),
                typeof(uint?),
                typeof(long),
                typeof(long?),
                typeof(ulong),
                typeof(ulong?),
                typeof(float),
                typeof(float?),
                typeof(double),
                typeof(double?),
                typeof(decimal),
                typeof(decimal?),
                typeof(string),
                typeof(DateTime),
                typeof(DateTime?),
            };

        #endregion

        #region Properties

        /// <summary>
        /// Determines whether this instance can convert the specified object type.
        /// </summary>
        /// <param name="objectType">Type of the object.</param>
        /// <returns>
        ///     <c>true</c> if this instance can convert the specified object type; otherwise, <c>false</c>.
        /// </returns>
        public override bool CanConvert(Type objectType)
        {
            // Note. Ideally this would match the test for JsonContractType.Array in DefaultContractResolver.CreateContract(),
            // but that code is all internal to Newtonsoft.Json.
            // Here we elect to take over conversion for Arrays only.
            if(!objectType.IsArray) {
                return false;
            }

            // Fast/efficient way of testing for multiple possible primitive types.
            Type elemType = objectType.GetElementType();
            return _primitiveTypeSet.Contains(elemType);
        }

        /// <summary>
        /// Gets a value indicating whether this <see cref="JsonConverter"/> can read JSON.
        /// </summary>
        /// <value>Always returns <c>false</c>.</value>
        public override bool CanRead
        {
            get { return false; }
        }

        #endregion

        #region Public Methods

        /// <summary>
        /// Reads the JSON representation of the object. (Not implemented on this converter).
        /// </summary>
        /// <param name="reader">The <see cref="JsonReader"/> to read from.</param>
        /// <param name="objectType">Type of the object.</param>
        /// <param name="existingValue">The existing value of object being read.</param>
        /// <param name="serializer">The calling serializer.</param>
        /// <returns>The object value.</returns>
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        /// Writes the JSON representation of the object.
        /// </summary>
        /// <param name="writer">The <see cref="JsonWriter"/> to write to.</param>
        /// <param name="value">The value.</param>
        /// <param name="serializer">The calling serializer.</param>
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            Formatting formatting = writer.Formatting;
            writer.WriteStartArray();
            try
            {
                writer.Formatting = Formatting.None;
                foreach(object childValue in ((System.Collections.IEnumerable)value)) {
                    serializer.Serialize(writer, childValue);
                }
            }
            finally
            {
                writer.WriteEndArray();
                writer.Formatting = formatting;
            }
        }

        #endregion
    }
}