300x250

studen_data.xlsx  => student_data.json

[
  {
    "id": 5000,
    "name": "길동이",
    "korean": 100,
    "math": 90,
    "english": 80
  },
  {
    "id": 5001,
    "name": "철수",
    "korean": 70,
    "math": 60,
    "english": 50
  },
  {
    "id": 5002,
    "name": "유리",
    "korean": 40,
    "math": 30,
    "english": 20
  },
  {
    "id": 5003,
    "name": "훈이",
    "korean": 10,
    "math": 0,
    "english": 10
  }
]

study_data.xlsx => study_data.json

[
  {
    "id": 200,
    "professor": "수학왕",
    "class_subject": "수학",
    "phone": "010-1234-5678"
  },
  {
    "id": 201,
    "professor": "영어킹",
    "class_subject": "영어",
    "phone": "010-9876-5432"
  },
  {
    "id": 202,
    "professor": "국어왕",
    "class_subject": "국어",
    "phone": "010-2222-3333"
  },
  {
    "id": 203,
    "professor": "코딩왕",
    "class_subject": "프로그래밍",
    "phone": "010-1111-2222"
  }
]

user_data.xlsx => user_data.json

[
  {
    "id": 1000,
    "name": "길동이",
    "weight": 40.3,
    "age": 8
  },
  {
    "id": 1001,
    "name": "철수",
    "weight": 41.3,
    "age": 9
  },
  {
    "id": 1002,
    "name": "유리",
    "weight": 43.5,
    "age": 10
  },
  {
    "id": 1003,
    "name": "훈이",
    "weight": 45.7,
    "age": 6
  }
]

 

위와같은 엑셀 데이터(xlsx) 파일을 json화 해서 C# 프로젝트에서 적용하는 방법을 정리 해봤어요.

데이터 파일을 json화를 했다면 (프로젝트에 도구 => NuGet 패키지 관리자(N) => 솔루션용 Nuget 패키지 관리)로 들어가줍니다.

 

 

들어가서 찾아보기탭을 누른다음 검색창에 newtonsoft.json을 검색한후에 우측에 현재 프로젝트를 선택하고 설치를 눌러줘요.

 

설치가 완료되면 솔루션 탐색기에서 참조 버튼을 눌렀을때 Newtonsoft.Json이 추가가 되있다면 준비는 끝난거에요.

 

저는 student_data.json과 매칭되는 클래스파일을 선언 해준 다음 데이터들을 관리해줄 싱글톤 클래스를 싱글톤으로 선언 해줬어요.

 

StudentData.cs

namespace SLG_CS_JsonExample
{   
    public class StudentData
    {        
        public int id;        
        public string name;        
        public int korean;        
        public int math;        
        public int english;
    }
}

 

DataManager.cs

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

namespace SLG_CS_JsonExample
{
    public sealed class DataManager
    {
        // 외부에서 접근 읽기 상태로만 접근할 수 있어 데이터 수정을 막고 데이터를 읽기만 할 수 있는 싱글톤 DataManager 선언
        public static readonly DataManager instance = new DataManager();

        // 딕셔너리로 데이터관리
        private Dictionary<int, StudentData> dicStudents = new Dictionary<int, StudentData>();

        private DataManager()
        {
        }

        // student_data.json 데이터를 불러와서 딕셔너리에 값을 저장하는 메소드
        public void LoadStudentDatas()
        {
            string json = File.ReadAllText("./student_data.json");
            // 역직렬화  : 문자열 -> 객체 
            StudentData[] studentDatas = JsonConvert.DeserializeObject<StudentData[]>(json);

            // 내부 람다의 의미는 배열에 담긴 객체의 속성중 키를 어떤것으로 할것인가?
            this.dicStudents = studentDatas.ToDictionary(x => x.id);    
        }

        // dicStudents에서 id값으로 데이터를 검색한 후 해당하는 데이터를 가져오는 메소드
        public StudentData GetStudentData(int id)
        {
            return this.dicStudents[id];
        }

        // dicStudents에 딕셔너리를 통째로 가져옴으로써 전체 데이터를 받아오는 메소드
        public Dictionary<int, StudentData> GetStudentDatas()
        {
            return this.dicStudents;
        }
    }
}

이렇게 해놓은 다음

 

DataTest.cs

using System;
using System.Collections.Generic;

namespace SLG_CS_JsonExample
{
    public class DataTest
    {
        public DataTest()
        {
            // json데이터를 불러와서 딕셔너리에 저장
            DataManager.instance.LoadStudentDatas();

            // 딕셔너리에 저장된 StudentData데이터딕셔너리를 통째로 DataManager 인스턴스에 접근하여 받아오기
            Dictionary<int, StudentData> studentDatas = DataManager.instance.GetStudentDatas();

            foreach (var studentData in studentDatas)
            {
                var id = studentData.Value.id;
                var name = studentData.Value.name;
                var korean = studentData.Value.korean;
                var math = studentData.Value.math;
                var english = studentData.Value.english;
                Console.WriteLine("id : {0}, name : {1}, korean : {2}, math : {3}, english : {4}", id, name, korean, math, english);
            }
            Console.WriteLine();
            Console.WriteLine();
            Console.WriteLine();
            Console.WriteLine("Search Data id : 5002");
            // 딕셔너리에 특정 데이터만 검색하여 접근하기
            StudentData searchData = DataManager.instance.GetStudentData(5002);

            Console.WriteLine("id : {0}, name : {1}, korean : {2}, math : {3}, english : {4}", 
                searchData.id, searchData.name, searchData.korean, searchData.math, searchData.english);
        }
    }
}

 

이런 식으로 사용할 수 있어요.

근데 이런 방식으로 하면 데이터파일이 증가할때마다

 

private Dictionary<int, StudentData> dicStudents = new Dictionary<int, StudentData>();

변수와 LoadStudentDatas(), GetStudentData(int id), GetStudentDatas() 메소드를 매번 정의 해줘야 해요.

모든 경우엔 할 수 없지만, 위에서 3개의 데이터엔 id라는 공통 필드가 있어요. 이 경우엔 이필드를 이용하여 일반화를 하면 좀 더 쉽게 데이터를 관리 할 수 있어요.

 

먼저 id값을 갖는 부모 클래스변수를 선언 해줘요.

RawData.cs

namespace SLG_CS_JsonExample
{
    public class RawData
    {
        public int id;
    }
}

그리고 데이터 클래스변수들은 이 클래스를 상속받아요.

StudentData.cs

namespace SLG_CS_JsonExample
{    
    public class UserData : RawData
    {            
        public string name;        
        public float weight;        
        public int age;
    }
}

Study.cs

namespace SLG_CS_JsonExample
{    
    public class StudyData : RawData
    {         
        public string professor;        
        public string class_subject;        
        public string phone;
    }
}

UserData.cs

namespace SLG_CS_JsonExample
{    
    public class UserData : RawData
    {            
        public string name;        
        public float weight;        
        public int age;
    }
}

이렇게 클래스들을 작성을 해준후 DataManager 에서 json데이터를 불러와서 저장하고 제가 직접 사용할수 있는 코드를 새로 작성해주면 되요.

DataManager.cs

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

namespace SLG_CS_JsonExample
{
    public sealed class DataManager
    {
        // 외부에서 접근 읽기 상태로만 접근할 수 있어 데이터 수정을 막고 데이터를 읽기만 할 수 있는 싱글톤 DataManager 선언
        public static readonly DataManager instance = new DataManager();

        // 딕셔너리로 데이터관리
        private Dictionary<int, RawData> dicDatas = new Dictionary<int, RawData>();

        private DataManager()
        {
        }

        // json 데이터를 불러와서 딕셔너리에 저장하는 메소드
        public void LoadData<T>(string path) where T : RawData
        {
            var json = File.ReadAllText(path);
            T[] arr = JsonConvert.DeserializeObject<T[]>(json);
            arr.ToDictionary(x => x.id).ToList().ForEach(x => dicDatas.Add(x.Key, x.Value));
        }

        // id 값으로 딕셔너리에서 검색하는 메소드
        public T GetData<T>(int id) where T : RawData
        {
            var collection = this.dicDatas.Values.Where(x => x.GetType().Equals(typeof(T)));
            return (T)collection.ToList().Find(x => x.id == id);
        }

        // 특정 데이터 그룹을 검색하고싶을대 해당 데이터 타입을 호출하면 해당 데이터타입 객체만 반환한다.
        // ex(GetDatas<Student>()) = 딕셔너리에 저장된 데이터들중 Student타입을 가진 객체들만 반환
        public IEnumerable<T> GetDatas<T>() where T : RawData
        {
            IEnumerable<RawData> col = this.dicDatas.Values.Where(x => x.GetType().Equals(typeof(T)));
            return col.Select(x => (T)Convert.ChangeType(x, typeof(T)));
        }
    }
}

 

아래는 DataManager를 실제 사용하여 데이터를 불러오는 예제에요.

DataTest.cs

using System;
using System.Linq;
using System.Collections.Generic;

namespace SLG_CS_JsonExample
{
    public class DataTest
    {
        public DataTest()
        {
            // json데이터를 불러와서 딕셔너리에 저장
            DataManager.instance.LoadData<StudentData>("./student_data.json");
            DataManager.instance.LoadData<StudyData>("./study_data.json");
            DataManager.instance.LoadData<UserData>("./user_data.json");

            // 딕셔너리에 저장된 StudentData데이터딕셔너리를 통째로 DataManager 인스턴스에 접근하여 받아오기
            IEnumerable<StudentData> studentDatas = DataManager.instance.GetDatas<StudentData>();
            List<StudentData> studentDataList = studentDatas.ToList();
            Console.WriteLine("=============studentDataList=============");
            foreach (var studentData in studentDataList)
            {
                var id = studentData.id;
                var name = studentData.name;
                var korean = studentData.korean;
                var math = studentData.math;
                var english = studentData.english;
                Console.WriteLine("id : {0}, name : {1}, korean : {2}, math : {3}, english : {4}", id, name, korean, math, english);
            }

            // 딕셔너리에 저장된 StudyData데이터딕셔너리를 통째로 DataManager 인스턴스에 접근하여 받아오기
            IEnumerable<StudyData> studyDatas = DataManager.instance.GetDatas<StudyData>();
            List<StudyData> studyDataList = studyDatas.ToList();
            Console.WriteLine("=============studyDataList=============");
            foreach (var studyData in studyDataList)
            {
                var id = studyData.id;
                var professor = studyData.professor;
                var class_subject = studyData.class_subject;
                var phone = studyData.phone;
                Console.WriteLine("id : {0}, professor : {1}, class_subject : {2}, phone : {3}", id, professor, class_subject, phone);
            }

            // 딕셔너리에 저장된 UserData데이터딕셔너리를 통째로 DataManager 인스턴스에 접근하여 받아오기
            IEnumerable<UserData> userDatas = DataManager.instance.GetDatas<UserData>();
            List<UserData> userDataList = userDatas.ToList();
            Console.WriteLine("=============userDataList=============");
            foreach (var userData in userDataList)
            {
                var id = userData.id;
                var name = userData.name;
                var weight = userData.weight;
                var age = userData.age;
                Console.WriteLine("id : {0}, name : {1}, weight : {2}, age : {3}", id, name, weight, age);
            }
            Console.WriteLine();
            Console.WriteLine("Search Data id : 5002");
            // 딕셔너리에 특정 데이터만 검색하여 접근하기
            StudentData searchData = DataManager.instance.GetData<StudentData>(5002);

            Console.WriteLine("id : {0}, name : {1}, korean : {2}, math : {3}, english : {4}", 
                searchData.id, searchData.name, searchData.korean, searchData.math, searchData.english);
        }
    }
}

300x250