programing

NameValueCollection을 JSON 문자열로 변환하는 방법

bestprogram 2023. 3. 28. 22:44

NameValueCollection을 JSON 문자열로 변환하는 방법

나는 시도했다.

  NameValueCollection Data = new NameValueCollection();
  Data.Add("foo","baa");
  string json = new JavaScriptSerializer().Serialize(Data);

반환:["foo"]기대했었어{"foo" : "baa"}이거 어떻게 해요?

Name Value Collection을 직렬화하는 방법 중 하나는 먼저 사전으로 변환한 다음 사전을 직렬화하는 것입니다.사전으로 변환하려면:

thenvc.AllKeys.ToDictionary(k => k, k => thenvc[k]);

변환을 자주 수행해야 하는 경우 NameValueCollection 확장 메서드를 만들 수도 있습니다.

public static class NVCExtender
{
    public static IDictionary<string, string> ToDictionary(
                                        this NameValueCollection source)
    {
        return source.AllKeys.ToDictionary(k => k, k => source[k]);
    }
}

다음과 같이 한 줄로 변환할 수 있습니다.

NameValueCollection Data = new NameValueCollection();
Data.Add("Foo", "baa");

var dict = Data.ToDictionary();

그런 다음 사전을 직렬화할 수 있습니다.

var json = new JavaScriptSerializer().Serialize(dict);
// you get {"Foo":"baa"}

그러나 NameValueCollection은 하나의 키에 대해 다음과 같은 여러 값을 가질 수 있습니다.

NameValueCollection Data = new NameValueCollection();
Data.Add("Foo", "baa");
Data.Add("Foo", "again?");

이것을 연재하면,{"Foo":"baa,again?"}.

변환기를 수정하여 다음을 생성할 수 있습니다.IDictionary<string, string[]>대신:

public static IDictionary<string, string[]> ToDictionary(
                                    this NameValueCollection source)
{
    return source.AllKeys.ToDictionary(k => k, k => source.GetValues(k));
}

따라서 다음과 같은 시리얼화된 값을 얻을 수 있습니다.{"Foo":["baa","again?"]}.

NameValueCollection사전이 아니기 때문에JavaScriptSerializer는, 직접 시리얼화할 수 없습니다.먼저 사전으로 변환한 다음 연재해야 합니다.

업데이트: 키당 여러 값에 대한 다음 문의:nvc[key]콤마로 구분하여 반환하기만 하면 됩니다.그렇지 않은 경우 언제든지 전화할 수 있습니다.GetValues그 값을 어떻게 할지를 결정하는 것입니다.다음 코드를 업데이트하여 가능한 한 가지 방법을 표시.

public class StackOverflow_7003740
{
    static Dictionary<string, object> NvcToDictionary(NameValueCollection nvc, bool handleMultipleValuesPerKey)
    {
        var result = new Dictionary<string, object>();
        foreach (string key in nvc.Keys)
        {
            if (handleMultipleValuesPerKey)
            {
                string[] values = nvc.GetValues(key);
                if (values.Length == 1)
                {
                    result.Add(key, values[0]);
                }
                else
                {
                    result.Add(key, values);
                }
            }
            else
            {
                result.Add(key, nvc[key]);
            }
        }

        return result;
    }

    public static void Test()
    {
        NameValueCollection nvc = new NameValueCollection();
        nvc.Add("foo", "bar");
        nvc.Add("multiple", "first");
        nvc.Add("multiple", "second");

        foreach (var handleMultipleValuesPerKey in new bool[] { false, true })
        {
            if (handleMultipleValuesPerKey)
            {
                Console.WriteLine("Using special handling for multiple values per key");
            }
            var dict = NvcToDictionary(nvc, handleMultipleValuesPerKey);
            string json = new JavaScriptSerializer().Serialize(dict);
            Console.WriteLine(json);
            Console.WriteLine();
        }
    }
}

사전이 많은 항목을 포함하지 않는 경우 클래스를 사용할 수 있습니다.System.Collections.Specialized.ListDictionary

Json을 사용하고 있는 한, 완전성을 위해, 그리고 질문이 계속되기 때문에(를 들면, 여기서) Json을 사용하고 있는 한).NET 또는 (단, 아님)어댑터 패턴을 사용하여NameValueCollection에 있어서IDictionary<string, string[]>어댑터 및 임의의 사전의 시리얼화를 완전히 지원하는 시리얼라이저를 사용하여 시리얼화합니다.

이러한 어댑터는 다음과 같습니다.

public class NameValueCollectionDictionaryAdapter<TNameValueCollection> : IDictionary<string, string[]>
    where TNameValueCollection : NameValueCollection, new()
{
    readonly TNameValueCollection collection;

    public NameValueCollectionDictionaryAdapter() : this(new TNameValueCollection()) { }

    public NameValueCollectionDictionaryAdapter(TNameValueCollection collection)
    {
        this.collection = collection;
    }

    // Method instead of a property to guarantee that nobody tries to serialize it.
    public TNameValueCollection GetCollection() { return collection; }

    #region IDictionary<string,string[]> Members

    public void Add(string key, string[] value)
    {
        if (collection.GetValues(key) != null)
            throw new ArgumentException("Duplicate key " + key);
        if (value == null)
            collection.Add(key, null);
        else
            foreach (var str in value)
                collection.Add(key, str);
    }

    public bool ContainsKey(string key) { return collection.GetValues(key) != null; }

    public ICollection<string> Keys { get { return collection.AllKeys; } }

    public bool Remove(string key)
    {
        bool found = ContainsKey(key);
        if (found)
            collection.Remove(key);
        return found;
    }

    public bool TryGetValue(string key, out string[] value)
    {
        return (value = collection.GetValues(key)) != null;
    }

    public ICollection<string[]> Values
    {
        get
        {
            return new ReadOnlyCollectionAdapter<KeyValuePair<string, string[]>, string[]>(this, p => p.Value);
        }
    }

    public string[] this[string key]
    {
        get
        {
            var value = collection.GetValues(key);
            if (value == null)
                throw new KeyNotFoundException(key);
            return value;
        }
        set
        {
            Remove(key);
            Add(key, value);
        }
    }

    #endregion

    #region ICollection<KeyValuePair<string,string[]>> Members

    public void Add(KeyValuePair<string, string[]> item) { Add(item.Key, item.Value); }

    public void Clear() { collection.Clear(); }

    public bool Contains(KeyValuePair<string, string[]> item)
    {
        string[] value;
        if (!TryGetValue(item.Key, out value))
            return false;
        return EqualityComparer<string[]>.Default.Equals(item.Value, value); // Consistent with Dictionary<TKey, TValue>
    }

    public void CopyTo(KeyValuePair<string, string[]>[] array, int arrayIndex)
    {
        foreach (var item in this)
            array[arrayIndex++] = item;
    }

    public int Count { get { return collection.Count; } }

    public bool IsReadOnly { get { return false; } }

    public bool Remove(KeyValuePair<string, string[]> item)
    {
        if (Contains(item))
            return Remove(item.Key);
        return false;
    }

    #endregion

    #region IEnumerable<KeyValuePair<string,string[]>> Members

    public IEnumerator<KeyValuePair<string, string[]>> GetEnumerator()
    {
        foreach (string key in collection)
            yield return new KeyValuePair<string, string[]>(key, collection.GetValues(key));
    }

    #endregion

    #region IEnumerable Members

    System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() { return GetEnumerator(); }

    #endregion
}

public static class NameValueCollectionExtensions
{
    public static NameValueCollectionDictionaryAdapter<TNameValueCollection> ToDictionaryAdapter<TNameValueCollection>(this TNameValueCollection collection)
        where TNameValueCollection : NameValueCollection, new()
    {
        if (collection == null)
            throw new ArgumentNullException();
        return new NameValueCollectionDictionaryAdapter<TNameValueCollection>(collection);
    }
}

public class ReadOnlyCollectionAdapter<TIn, TOut> : CollectionAdapterBase<TIn, TOut, ICollection<TIn>>
{
    public ReadOnlyCollectionAdapter(ICollection<TIn> collection, Func<TIn, TOut> toOuter)
        : base(() => collection, toOuter)
    {
    }

    public override void Add(TOut item) { throw new NotImplementedException(); }

    public override void Clear() { throw new NotImplementedException(); }

    public override bool IsReadOnly { get { return true; } }

    public override bool Remove(TOut item) { throw new NotImplementedException(); }
}

public abstract class CollectionAdapterBase<TIn, TOut, TCollection> : ICollection<TOut> 
    where TCollection : ICollection<TIn>
{
    readonly Func<TCollection> getCollection;
    readonly Func<TIn, TOut> toOuter;

    public CollectionAdapterBase(Func<TCollection> getCollection, Func<TIn, TOut> toOuter)
    {
        if (getCollection == null || toOuter == null)
            throw new ArgumentNullException();
        this.getCollection = getCollection;
        this.toOuter = toOuter;
    }

    protected TCollection Collection { get { return getCollection(); } }

    protected TOut ToOuter(TIn inner) { return toOuter(inner); }

    #region ICollection<TOut> Members

    public abstract void Add(TOut item);

    public abstract void Clear();

    public virtual bool Contains(TOut item)
    {
        var comparer = EqualityComparer<TOut>.Default;
        foreach (var member in Collection)
            if (comparer.Equals(item, ToOuter(member)))
                return true;
        return false;
    }

    public void CopyTo(TOut[] array, int arrayIndex)
    {
        foreach (var item in this)
            array[arrayIndex++] = item;
    }

    public int Count { get { return Collection.Count; } }

    public abstract bool IsReadOnly { get; }

    public abstract bool Remove(TOut item);

    #endregion

    #region IEnumerable<TOut> Members

    public IEnumerator<TOut> GetEnumerator()
    {
        foreach (var item in Collection)
            yield return ToOuter(item);
    }

    #endregion

    #region IEnumerable Members

    IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); }

    #endregion
}

그런 다음 주어진 시간에 맞게 적응된 것을 구성할 수 있습니다.NameValueCollection Data간단하게 할 수 있습니다.

var adapter = Data.ToDictionaryAdapter();

주의:

  • 어댑터를 사용하면 단순히 복사된 사전을 작성하는 것보다 성능이 향상될 수 있습니다.또, 사전의 시리얼화를 완전하게 서포트하고 있는 시리얼 라이저에서는 정상적으로 동작할 수 있습니다.

    이 어댑터는 또한 다음 기능을 사용할 때 유용할 수 있습니다.NameValueCollection다른 코드와 조합하여IDictionary일종의 - 이것이 어댑터 패턴의 근본적인 장점입니다.

  • 말하자면JavaScriptSerializer이 직렬화기는 구현 중인 임의 유형을 직렬화할 수 없으므로 어댑터와 함께 사용할 수 없습니다.IDictionary<TKey, TValue>에서 Dictionary<TKey, TValue>자세한 내용은 JavaScript Serializer를 사용한 사전 시리얼화를 참조하십시오.

  • 「」를 사용하고 DataContractJsonSerializer ,a ,aNameValueCollection는 데이터 계약 대리 메커니즘을 사용하여 시리얼화 그래프의 어댑터로 대체할 수 있습니다.

  • Json j j j j j j 。 a '''a''NameValueCollection는 다음과 같은 커스텀을 사용하여 어댑터로 교체할 수 있습니다.

    public class NameValueJsonConverter<TNameValueCollection> : JsonConverter
        where TNameValueCollection : NameValueCollection, new()
    {
        public override bool CanConvert(Type objectType)
        {
            return typeof(TNameValueCollection).IsAssignableFrom(objectType);
        }
    
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            if (reader.SkipComments().TokenType == JsonToken.Null)
                return null;
    
            // Reuse the existing NameValueCollection if present
            var collection = (TNameValueCollection)existingValue ?? new TNameValueCollection();
            var dictionaryWrapper = collection.ToDictionaryAdapter();
    
            serializer.Populate(reader, dictionaryWrapper);
    
            return collection;
        }
    
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            var collection = (TNameValueCollection)value;
            var dictionaryWrapper = new NameValueCollectionDictionaryAdapter<TNameValueCollection>(collection);
            serializer.Serialize(writer, dictionaryWrapper);
        }
    }
    
    public static partial class JsonExtensions
    {
        public static JsonReader SkipComments(this JsonReader reader)
        {
            while (reader.TokenType == JsonToken.Comment && reader.Read())
                ;
            return reader;
        }
    }
    

    예를 들어 다음과 같이 사용할 수 있습니다.

    string json = JsonConvert.SerializeObject(Data, Formatting.Indented, new NameValueJsonConverter<NameValueCollection>());
    
  • NameValueCollection의 모든 합니다.

    • A null값; ""
    • 특정 키에 대한 여러 값(이 경우 쉼표로 구분된 값 목록을 반환합니다)
    • 콤마를 값(''를 사용하는 할 수 .NameValueCollection.Item[String]를 참조해 주세요.


    는 '어댑터'를 구현해야 .IDictionary<string, string[]>IDictionary<string, string> '나'나 '나'나 '나'나 '나'나 '나'나 '나'나 '나'나 '나'나 '나'나 '나'나 '나' 같은 것도null값 배열

바이올린의 샘플(일부 기본적인 유닛 테스트 포함)은, https://dotnetfiddle.net/gVPSi7 를 참조해 주세요.

언급URL : https://stackoverflow.com/questions/7003740/how-to-convert-namevaluecollection-to-json-string