본문 바로가기

C#/근웹 연대기

c#으로 근본 없는 웹서버 개발기 13 : json stringify 만들기

⚠WARNING
ASP.NET에 대한 포스팅이 아닙니다
나가실 문은 오른쪽 하단입니다

 

 

서버가 브라우저와 비동기 통신을 할 때, 주로 JSON형태의 데이터를 주고받는다.

c#에서 이러한 것을 다룰 때는, 편리한 도구 같은 것이 내부 라이브러리에는 없는지라, 외부 패키지인 Newtonsoft社의 Json.net을 사용한다.

 

그런데 지금까지 연대기에서는 외부 패키지를 사용하지 않았다.

그렇다

외부 패키지를 쓸 거였으면 지금까지 한 땀 한 땀 코딩했던 것들이 의미가 없는 것이 된다.

그렇다

이미 완전한 물건을 쓴다면 그 물건에 대한 애착은 그다지 끈끈하지 않을 것이다.

그렇다

부족하니까 채워주고 싶은 욕구다.

부족하니까 채우는 즐거움이 있다

 

우선 전체적인 계획 없이 다음과 같이 근본이 되는 클래스를 작성하였다.

public abstract class J
{
    public static JO O(params ValueTuple<object, object>[] args) => new JO(args);
    public static JL L(params object[] args) => new JL(args);
    public dynamic this[object key]
    {
        get => getValue(key);
        set => setValue(key, value);
    }
    public abstract void setValue(object key, object value);
    public abstract object getValue(object key);
    public abstract void Add(object value);
    public abstract List<Object> getList();

    protected string ifAddQuotes(object o) => o switch
    {
        String x => $"\"{Escape(x)}\"",
        null => "null",
        _ => o.ToString()
    };
    public abstract string stringify();

    public static J parse(string str)
    {
        throw new NotImplementedException();
    }
}

NotImplementedException부분은 손이 많이 가는 부분으로 나중에 하겠다.

 

그리고 나서 서브클래스를 각각 작성하였다.

public class JO : J
{
    Dictionary<String, object> dic = new();
    public JO() { }
    public JO(ValueTuple<object, object>[] args)
    {
        foreach (var tem in args) dic.Add("" + tem.Item1, tem.Item2);
    }
    public override object getValue(object key) => dic.GetValueOrDefault(key.ToString());
    public override void setValue(object key, object value) => dic[key.ToString()] = value;
    public override void Add(Object value) => dic.Add(value.ToString(), null);

    public override List<Object> getList() => dic.Keys.Select(x => x as object).ToList();

    public override string stringify()
    {
        var lq = from x in dic
                 select ifAddQuotes(x.Key) + ":"
                 + ((x.Value as J)?.stringify() ?? ifAddQuotes(x.Value));
                 
        return $"{{{String.Join(", ", lq)}}}";
    }
}

이름에 알 수 있듯이, 오브젝트 타입이다.

 

public class JL : J
{
    List<Object> li = new();
    public JL() { }
    public JL(object[] args)
    {
        foreach (var tem in args) li.Add(tem);
    }
    public override object getValue(object key) => li.ElementAtOrDefault((int)key);
    public override void setValue(object key, object value) => li[(int)key] = value;
    public override void Add(Object value) => li.Add(value);
    public override List<Object> getList() => li;

    public override string stringify()
    {
        var lq = li.Select(x => (x as J)?.stringify() ?? ifAddQuotes(x));
 
        return $"[{String.Join(", ", lq)}]";
    }
}

이름에서 알 수 있듯이, 리스트 타입이다.

 

 

마지막으로 다음의 코드로 테스트를 하였다.

var j = J.O((1, J.L(1,2, J.L(1.1 ,1.2, 1.3), 4,"5")), ("key","value"));

Console.WriteLine(j.stringify());

클래스명이 짧아 보기가 좋은듯하다.

 

 

Escape :

2022.03.08 - [C#/예제 코드] - c# 자바스크립트 문자열 encode & decode (escape)